我应该如何更新 Matlab 中的绘图数据? [英] How should I update the data of a plot in Matlab?

查看:133
本文介绍了我应该如何更新 Matlab 中的绘图数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我想用新数据更新绘图.我应该选择什么方法?

  1. XDataSource 属性设置为某个名称,更新变量,然后调用refreshdata
  2. 擦除原来的plot,再次调用plot命令.
  3. 使用Set('Xdata',...')

解决方案

Short answer : always use Set('Xdata',...').>

示例代码:

函数 PlotUpdate()x = 0:.1:8;y = 罪 (x);h = 情节(x,y);y = sin(x.^3);set(h,'XData',x,'YData',y);结尾

<小时>

长答案:

选择最佳方法的三个相关措施.

  1. 代码清晰 - 别人阅读你的代码有多容易?
  2. 运行时 - 每种方法执行其任务的速度有多快?
  3. 代码可移植性 - 重构代码的速度有多快?

现在,让我们分析一下可能的方法.

方法(1) - 刷新数据

函数 PlotUpdate()x = 0:.1:8;y = 罪 (x);h = 情节(x,y);设置(h,'YDataSource','y')设置(h,'XDataSource','x')y = sin(x.^3);刷新数据(h,'调用者');结尾

M-lint 立即在 y=sin(x.^3)

行发出警告

分配给变量`y`的值可能未被使用

为什么会这样?refreshdata 使用 evalm-lint 无法知道您将使用 y.有人阅读您的代码,不妨完全删除这一行.发生这种情况是因为您违反了封装原则.refreshdata 从调用者工作区访问变量.另一种看待这个的方法,假设您将绘图的句柄传递给另一个函数.读者不知道你到底为什么写y = sin(x.^3);,以及它与剧情的更新有什么关系.

现在让我们讨论速度/运行时间.通过查看refreshdata 源代码,您会注意到两个丑陋的for 循环,它们遍历所有 图形处理空间中的变量.这是第一个:

% 收集所有要刷新的对象对象 = {};对于 k = 1:length(h)obj = h(k);对象字段 = 字段(对象);对于 k2 = 1:length(objfields)% 搜索以 DataSource 结尾的属性如果 strncmpi(fliplr(objfields{k2}),'ecruoSataD',10)objs = {objs{:},obj, objfields{k2}};结尾结尾结尾

假设您没有一个图,而是 100 个图,并且您只想更新第一个图.这将非常缓慢,因为对于每个地块,您都试图找到您需要的地块!(我将离开作为练习让读者弄清楚什么是 ecruoSataD,以及它是如何使用的.)

即使您将相关图作为参数,您仍然有第二个循环,该循环多次运行 eval.不完全有效.最后我会展示一个时间对比.

结论:难理解、难重构、运行缓慢

<小时>

方法 (2) - 删除并重新绘制

函数 PlotUpdate()x = 0:.1:8;y = 罪 (x);h = 情节(x,y);设置(h,'YDataSource','y')设置(h,'XDataSource','x')y = sin(x.^3);删除(h);h = 情节(x,y);结尾

这个方法对读者来说已经很清楚了.你删除了情节,画了一个新的.但是,正如我们从最后的时间比较中看到的那样,这是最慢的方法.

结论:易于理解,易于重构,运行速度非常慢

<小时>

方法(3) - set('XData',...,'YData')

代码很清楚.您想修改绘图的两个属性,XDataYData.而这正是你所做的.此外,代码运行速度非常快,从下面的比较中可以看出.

函数 PlotUpdate()x = 0:.1:8;y = 罪 (x);h = 情节(x,y);y = sin(x.^3);set(h,'XData',x,'YData',y);结尾

自从新的图形引擎 hg2(R2014b 及更高版本)以来,如果您喜欢这种表示法,您还可以使用属性语法来指定数据:

函数 PlotUpdate()x = 0:.1:8;y = 罪 (x);h = 情节(x,y);y = sin(x.^3);h.XData = x;h.YData = y;结尾

结论:易于理解,易于重构,运行速度快

<小时>

这里是时间对比代码

function PlotUpdateTimeCompare()x = 0:.1:8;y = 罪 (x);h = 情节(x,y);设置(h,'YDataSource','y')设置(h,'XDataSource','x')y = sin(x.^3);抽动对于 i=1:100刷新数据(h,'调用者');结尾目录抽动对于 i=1:100删除(h);h = 情节(x,y);结尾目录抽动对于 i=1:100set(h,'XData',x,'YData',y);结尾目录结尾

结果:

<块引用>

经过的时间是 0.075515 秒.
经过的时间是 0.179954 秒.
经过的时间是 0.002820 秒.

Suppose that I want to update a plot with a new data. What method should I choose?

  1. Set the XDataSource property to some name, update the variable, and call refreshdata
  2. Erase the original plot, and call plot command again.
  3. Use Set('Xdata',...')

解决方案

Short answer : always use Set('Xdata',...').

Example code:

function PlotUpdate()   
    x = 0:.1:8;
    y = sin(x);
    h = plot(x,y);
    y = sin(x.^3);    
    set(h,'XData',x,'YData',y);
end


Long answer:

There are three relevant measures by which one should choose the best method.

  1. Code clarity - How easy it is for someone to read your code?
  2. Runtime - How quick each method performs its task?
  3. Code portability - How fast can you re-factor your code?

Now, let's analyze the possible methods.

Method(1) - refreshdata

function PlotUpdate()   
    x = 0:.1:8;
    y = sin(x);
    h = plot(x,y);
    set(h,'YDataSource','y')
    set(h,'XDataSource','x')
    y = sin(x.^3);
    refreshdata(h,'caller');
end

M-lint immediately issues a warning in the line y=sin(x.^3)

The value assigned to variable `y` might be unused

Why does it happen? refreshdata uses eval and m-lint cannot know that you will use y. Someone reading your code, might as well remove this line completely. This happened because you broke the encapsulation principle. refreshdata accesses variables from the caller workspace. Another way to take a look at this, suppose that you pass the handle of the plot to another function. The reader has no clue to why on earth you wrote y = sin(x.^3);, and how is it going to be related to the update of the plot.

Now let's discuss speed/runtime. By taking a look at refreshdata source code, you will notice two ugly for-loops, that go through all of the graphics handles variables in your space. Here is the first:

% gather up all the objects to refresh
objs = {};
for k = 1:length(h)
  obj = h(k);
  objfields = fields(obj);
  for k2 = 1:length(objfields)
    % search for properties ending in DataSource
    if strncmpi(fliplr(objfields{k2}),'ecruoSataD',10)
      objs = {objs{:},obj, objfields{k2}};
    end
  end
end

Imagine that you have not one plot, but 100 plot and you want to update only the first. This will be very slow, because for each of the plots, you attempt to find the one you need! (I am leaving as an exercise for the reader to figure out what is ecruoSataD, and how it is used.)

Even if you give the relevant plot as an argument, you still have the second loop, that runs eval several times. Not exactly efficient. I will show a time comparison in the end.

Conclusion : Hard to understand, hard to refactor, slow runtime


Method (2) - Delete and re-plot

function PlotUpdate()   
    x = 0:.1:8;
    y = sin(x);
    h = plot(x,y);
    set(h,'YDataSource','y')
    set(h,'XDataSource','x')
    y = sin(x.^3);          
    delete(h);
    h = plot(x,y);    
end

This method is quite clear for the reader. You deleted the plot, and drew a new one. However, as we will see from the time comparison in the end, that is the slowest method.

Conclusion : Easy to understand, easy to refactor, very slow runtime


Method(3) - set('XData',...,'YData')

The code is really clear. You want to modify a two properties of your plot, XData and YData. And that is exactly what you do. Also, the code runs really fast, as you can see from the comparison below.

function PlotUpdate()   
    x = 0:.1:8;
    y = sin(x);
    h = plot(x,y);
    y = sin(x.^3);          
    set(h,'XData',x,'YData',y);
end

Since the new graphics engine hg2 (R2014b and up), you can also use property syntax for specifying data if you prefer that notation:

function PlotUpdate()   
    x = 0:.1:8;
    y = sin(x);
    h = plot(x,y);
    y = sin(x.^3);          
    h.XData = x;
    h.YData = y;
end

Conclusion : Easy to understand, easy to refactor, fast runtime


Here is the time comparison code

function PlotUpdateTimeCompare()    
    x = 0:.1:8;
    y = sin(x);
    h = plot(x,y);
    set(h,'YDataSource','y')
    set(h,'XDataSource','x')
    y = sin(x.^3);


    tic
    for i=1:100
        refreshdata(h,'caller');
    end
    toc 

    tic
    for i=1:100
        delete(h);
        h = plot(x,y);
    end
    toc     

    tic
    for i=1:100
        set(h,'XData',x,'YData',y);
    end
    toc 

end

And the results:

Elapsed time is 0.075515 seconds.
Elapsed time is 0.179954 seconds.
Elapsed time is 0.002820 seconds.

这篇关于我应该如何更新 Matlab 中的绘图数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆