简体   繁体   English

为什么MATLAB的图例功能如此之慢,以及如何优化?

[英]Why is MATLAB's legend function so slow, and how to optimize?

Problem 问题

In a GUI I've written I've realized that the largest bottleneck in my code performance is creating/updating the legend. 在我写的GUI中,我意识到我的代码性能中最大的瓶颈是创建/更新图例。

Currently I delete and recreate the legend at each update of the GUI as the user needs to be able to adjust what is in the legend. 目前,我在每次更新GUI时删除并重新创建图例,因为用户需要能够调整图例中的内容。 I'm currently toggling what is in the legend by adjusting the setting of LINEHANDLE.Annotation.LegendInformation.IconDisplayStyle and updating the legend using legend('off');legend('show'); 我正在通过调整LINEHANDLE.Annotation.LegendInformation.IconDisplayStyle的设置来切换图例中的内容,并使用legend('off');legend('show');更新图例legend('off');legend('show');

Testing 测试

The following code snippet shows that the call of legend mostly is limited by the call to legend>make_legend and is fairly independent of the legend content. 以下代码片段显示, legend调用主要受到对legend>make_legend的调用的限制,并且完全独立于图例内容。

close all

n=50; % number of plot lines
S=rand(n); % data
legs=cellstr(char(26*rand(n,10)+97)); % legend entries

profile on %start profiler
plot(S)
legend(legs{:})
profile viewer % view call stats

Question

Is there a better way of updating legend content without deleting it and therefore forcing it to re-call make_legend at recreation? 是否有更好的方法来更新图例内容而不删除它,因此强制它在娱乐时重新调用make_legend

Furthermore I wonder if it is known why legend in general is so slow and has such odd behavior. 此外,我想知道为什么一般的legend是如此缓慢和具有如此奇怪的行为。

Purpose 目的

I'm adding some information here to avoid the XY Problem . 我在这里添加一些信息以避免XY问题 A minimal example of what I'm trying to do is: 我正在尝试做的最小例子是:

I'm building a GUI which plots four lines, let's call them data1 , data2 , linear model 1 , and linear model 2 . 我正在构建一个绘制四行的GUI,我们称之为data1data2linear model 1linear model 2 The data lines are independent in both color and content, while the linear models both have the same appearance and are connected to respective data line. 数据线在颜色和内容上都是独立的,而线性模型具有相同的外观并且连接到相应的数据线。

I want there to be a legend which only has three entries: data1 , data2 , and linear model . 我希望有一个只有三个条目的图例: data1data2linear model So far, no problem. 到目前为止,没问题。

I also want there to be three toggle-buttons which toggle the visibility of the four lines on the axes and legend. 我还希望有三个切换按钮,用于切换轴和图例上四条线的可见性。 The buttons are: 按钮是:

  • data1 , which toggles the visibility of both the data1 , and linear model 1 data lines. data1 ,用于切换data1linear model 1数据行的可见性。
  • data2 , which toggles the visibility of both the data2 , and linear model 2 data lines. data2 ,用于切换data2linear model 2数据线的可见性。
  • linear model , which toggles the visibility of the linear model 1 , and linear model 2 data lines. linear model ,用于切换linear model 1linear model 2数据线的可见性。

Attempted Solutions 试图解决方案

My first approach was to first only pass three handles to legend and then have the button callbacks adjust the visibility property of the line objects according to above. 我的第一种方法是首先只将三个句柄传递给legend ,然后让按钮回调根据上面的内容调整线对象的visibility属性。

This creates the issue that when disabling the first data line and respective linear model the legend entry for linear model also blanks out as it is connected to that specific line object, even though the other is still visible. 这将创建禁用第一数据线和相应的线性模型时的图例项问题linear model也清空了,因为它是连接到特定的线对象,即使对方依然可见。

My current working approach instead manually sets the DisplayName property of all lines and then the button callbacks adjust each lines Annotation.LegendInformation.IconDisplayStyle property. 我当前的工作方法是手动设置所有行的DisplayName属性,然后按钮回调调整每行Annotation.LegendInformation.IconDisplayStyle属性。 According to the documentation the user then needs to call legend to force an update. 根据文档 ,用户然后需要调用legend来强制更新。

But this is not implemented, looking at the code of legend.m it is clear that this option only returns the current legend object without any other manipulation. 但是这没有实现,查看legend.m的代码很明显,此选项仅返回当前图例对象而不进行任何其他操作。 Therefore I'm forced to call legend('off');legend('show'); 因此我被迫称为legend('off');legend('show'); which triggers a (slow) creation of a new legend object. 它会触发(慢速)创建新的图例对象。

This currently works but using profile I can see that the legend creation is half my computation time and has a fairly large effect on user experience when using the GUI on a slower laptop. 这当前有效,但使用profile我可以看到,图例创建是我的计算时间的一半,并且在较慢的笔记本电脑上使用GUI时对用户体验有相当大的影响。 I've already ensured that my code runs legend('off');legend('show'); 我已经确保我的代码运行legend('off');legend('show'); only if it really has to. 只有它真的必须。

The question is if any user here is able to call the unreadable, yet accessible class methods of matlab.graphics.illustration.Legend to trigger an update of an existing object without forcing it to delete and recreate. 问题是,这里的任何用户是否能够调用matlab.graphics.illustration.Legend的不可读但可访问的类方法来触发现有对象的更新而不强制它删除和重新创建。 Thereby doing what the MATHWORKS documentation claims to be implemented (although it is not) in legend . 从而做了MATHWORKS文档声称在legend实现的内容(尽管它不是)。

Alternatively I'm open to finding a different way of changing which line objects the current legend is tracking efficiently. 或者,我愿意找到一种不同的方式来更改当前图例有效跟踪的线对象。

You can try to change the properties of the legend object directly. 您可以尝试直接更改图例对象的属性。 Look at http://www.mathworks.com/help/matlab/ref/legend-properties.html for a list of properties. 请访问http://www.mathworks.com/help/matlab/ref/legend-properties.html以获取属性列表。 The legend object can be accessed by: 图例对象可以通过以下方式访问:

% Assign the output of legend to a variable. Do this only once at creation.
l = legend(<some arguments>); 

% Example: change the location of the legend to 'north'
l.Location = 'north'; 

I think this is what you asked for, but I'm not sure about any efficiency gains. 我认为这就是你要求的,但我不确定任何效率提升。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM