Hi. I'm creating apps on app designer which use components such as sliders to control a plot. When plotting on a UIAxes, there is significant delay. However, when having the app plot on a separate figure, there is no delay. Does anyone know the reason for this and if there's a way to plot on the UIAxes without the delay? Thanks.
I'm going to use an app modelling a cylinder removing a lot of the additional unnecessary stuff, so the type of problem is as clear as possible. The plot consists of surf, patch, and plot3. For all apps, the goal is not plotting data per say, but rather creating shapes, often in 3 dimensions. Therefore, the data is generally arrays of type double which don't generally get over 100 elements.
I'm using MATLAB R2020a.
These are the two methods:
  • I drag and drop a UIAxes on to the app and plot on that axis. This takes about 3 seconds to update the plot each time I move the slider. This is a screenshot of the setup:
  • I create a separate regular figure (not uifigure) and plot it on that. This has almost no delay:
This is the code used to create the separate figure and have them aligned neatly (I don't think it's that important but it clarifies what I'm doing):
global ax %needed so it can be accessed through component callbacks
divide=.2;%the fraction of the screen filled by the app
set(0,'units','pixels')
pixels=get(0,'screensize');
app.UIFigure.Position=[0,0,divide*pixels(3),pixels(4)];
fig=figure; %new figure
fig.Position=[divide*pixels(3),0,(1-divide)*pixels(3),pixels(4)];
ax=axes(fig); %axis it will be plotted on
Here is the code which I used (I removed much of the code used in the original app to simplify things) (the code is based off of Clay M. Thompson's cylinder function, and I kept the copyright text in the code):
function torsion(ax,ax2,M,G,L,r,display_in)
% Clay M. Thompson 4-24-91, CBM 8-21-92.
% Copyright 1984-2002 The MathWorks, Inc.
cla(ax)
% engineering equations:
J=1/4*r^4;
phi=M*L/(J*G);
% set up cylinder:
n = 50;
r = [r r]';
r = r(:); % Make sure r is a vector.
m = length(r); if m==1, r = [r;r]; m = 2; end
theta = (0:n)/n*2*pi;
sintheta = sin(theta); sintheta(n+1) = 0;
x = r * cos(theta);
y = r * sintheta;
z = (0:m-1)'/(m-1) *L* ones(1,n+1);
hold(ax,'on')
% plot cylinder
surf(ax,x,y,z,'EdgeColor','none','FaceAlpha',1)
patch(ax,x(1,:),y(1,:),z(1,:),[.25 0 .7])
patch(ax,x(1,:),y(1,:),z(2,:),[.25 0 .7])
%plot helices
z_vals=linspace(0,L,n*L/(2*pi*r(1)));
for i=0:n-1
angle0=i*(2*pi)/n;
anglef=angle0+phi;
theta_part=linspace(angle0,anglef,length(z_vals));
x_part=(r*1.01)*cos(theta_part);
y_part=(r*1.01)*sin(theta_part);
z_vals=linspace(0,L,length(x_part));
plot3(ax,x_part,y_part,z_vals,'k','LineWidth',.5)
end
% plot circles
for i=z_vals
plot3(ax,x,y,i*ones(1,n+1),'k','LineWidth',.5)
end
end

14 Comments

is the separate figure created using "figure" or "uifigure"? I've also perceived (no hard data) that the new uifigure system is generally slower...
if using uifigure, are you creating a "uiaxes" inside it, or just an "axes"?
Ephraim, can you share a little more info? Specifically:
  • What kind of plot you're creating
  • Data sizes / datatypes you're trying to display
  • Sample code you're using that might illustrate the problem
  • What MATLAB release you're working on
Thanks!
Thanks for the responses! I updated the question with the information.
Could you attach the app, any data needed to run the app, and instructions on how to use the app to recreate the problem?
There are some suboptimalities in the code you shared that probably aren't causing the timing issues but could potentially cause other problems at some point.
1) Don't use global variables. The correct way to pass variables from within the app is to define public or private properties. Instructions:
2) Rather than using set(0, ___), set the properties to specific objects.
What's up with the last loop? Nothing changes within the loop so you're just plotting the same thing repeatedly.
Here is the link to the app on File Exchange. No data is needed to run it, simply run the TORSION file. The app also has some additional things displayed (e.g. text to label the cylinder) so you won't be able to recreate the screenshots exactly, but you can just adjust the sliders to get to the same position as the screenshots.
Thank you for your advice. I will use app properties for the axis from now on and set the units to the specific object.
The last loop plots circles at different heights (the i value changes in each iteration, changing the z position).
Adam Danz
Adam Danz on 6 Aug 2020
Edited: Adam Danz on 6 Aug 2020
I'm really confused here. Your question is about a uiaxis but your app doesn't contain a uiaxis.
Also the figure sizes are so large that I cannot work with them and have to manually resize them before I can do anything else. It would be much better to remove the figure possition commands and to let the user resize the app as needed.
Ephraim Bryski
Ephraim Bryski on 6 Aug 2020
Edited: Ephraim Bryski on 6 Aug 2020
No, it doesn't. I would like to use a UIAxes instead of creating a separate figure, but it is very slow if I take that approach.
I didn't know that the figures don't fit when using a different computer (I've only seen it on mine so far). I think I'll make that change.
@Ephraim Bryski & @Chris Portal, I timed the startupFcn which does all of the plotting and some other stuff (much of which is suboptimal) and compared the timing when an embedded uiaxis is used within the app and when the external figure and (regular) axis is created. This was repeated 10 times. Results are below. Note that the app-uiaxes are created prior to the tic-toc time but the external figure and axes are created within the tic-toc time. Nevertheless, the independent axis version is ~7x faster (MATLAB Version: 9.7.0.1296695 (R2019b) Update 4).
I ran the profiler on the startup function using the app's uiaxis which shows the greatest Self Time within UIAxis.set.View.
Thank you so much! I couldn't figure out how to run and time for an app. How were you able to do this?
I don't really understand what UIAxes>UIAxes.set.View is or how to optimize it. Do you think there's an way to speed it up? I also would guess that this might only be called in the startup function and not for each callback, in which case speeding it up wouldn't actually make it faster when using the app.
A simply way to time a section of code is by using tic and toc (check out the documentation).
Example
tic
x = linspace(-pi,pi,180);
y = sin(x);
plot(x,y)
toc
The timing report was produced using profile. Again, see documentation.
profile on
% DO STUFF
profile viewer
Most of the stuff in the timing report I shared, including the line I highlighted, is stuff happening behind the scenes. You can't optimize much of that. However, there's a few suboptimalities in your startupFcn. I've shut down Matlab for the day so I can't view the code now but I did highlight two items in my first comment in this thread. I also recall seeing two axes being created but only one was used.
Adam Danz
Adam Danz on 22 Mar 2021
Edited: Adam Danz on 22 Mar 2021
Here's an update with Marlab r2020b and r2021a but the methodology differs from the r2019b figure
The production of UIFigure/UIAxes and figure/axes was repeated 11 times and timed using tic/toc including the drawnow command so that the figure renders within the clock time. The timing of iterations 2 to 11 are plotted for comparison (the first iteration is ignored since it may consume more time that subsequent repetitions due to JIT compilation).
Script attached (uifigure_uiaxes_timing.m).
Windows 10; 16GB RAM Intel Core i7 CPU
I repeated the r2021a test several times and the variation in timing for UIFigures & UIAxes was persistent in all repetitions.
In Adam's test (for 2020b), it appears the time is really spent by the uifigure call, not the uiaxes call. Here's a variation on the test for all 4 combinations.
And I have felt, at least, that it is not necessarily creation, but interaction with uiaxes that has been slow...so here's a simple plotting comparison, though actually it seems to be the opposite...maybe i have perceived lagging on things like resizing...but too lazy to do this now.
Adam Danz
Adam Danz on 25 Mar 2021
Edited: Adam Danz on 25 Mar 2021
Good thinking to time them that way, J. Alex Lee.
Actually, the creation of figures and axes can be completely separated if the tic/toc only surrounds either the figure creation of the axes creation with a drawnow preceeding the creation.
thanks @Adam Danz, I think I actually confused everyone with my above posted...the way I separated was to create the figures once and for all, and then keep deleting and creating axes inside them - so the plot I showed only reflects axes creation time, and the conclusion from that should not be "ime is really spent by the uifigure call", but rather that creating uiaxes and axes alike within an existing uifigure is slower than creating them within an existing regular figure.
And the second time test I did shows that actually, plotting might be faster within uiaxes than in regular axes once they are created, whether it be within a uifigure or a regular figure. but either way, plotting is still much faster on uiaxes or axes created in a normal figure.

Sign in to comment.

 Accepted Answer

Chris Portal
Chris Portal on 7 Aug 2020

5 votes

Thank you @Adam Danz and @Ephraim Bryski. The additional info is useful. I see the same uifigure/uiaxes slowness Adam is showing.
Ephraim, try using a uifigure/axes combination instead. This shows similar performance results to the figure/axes combination:
  • UIFIGURE/UIAXES: Elapsed time is 1.871439 seconds.
  • UIFIGURE/AXES: Elapsed time is 0.205658 seconds.
  • FIGURE/AXES: Elapsed time is 0.204895 seconds.
A few notes:
  • UIAXES is a heavier weight version of AXES (it's effectively an axes with an invisible UI panel). This makes it slower, although the amount of slowness here is a little surprising. I'll report this to the development team to investigate.
  • The axes you get in App Designer when you drag and drop from the palette is always a UIAXES. So in order to use an AXES with your UIFIGURE, you'll need to manually create and position it as part of your startup function.
  • Lastly, these UIAXES/AXES differences will soon become a much simpler story with some up and coming work. Keep an eye out for the MATLAB release notes!

19 Comments

Florin
Florin on 30 Sep 2020
Hello,
Are the app-uiaxes issues solved with 2020b? (reading in the relase notes:'Also, UIAxes objects now have the same properties and options as Axes objects have for customizing their appearance and behavior:')
I am using this method: https://www.mathworks.com/help/matlab/ref/uigridlayout.html#mw_9f162f16-28ed-46bb-8bfa-cbd2efd0d143 to show/hide some grids in App Designer containing uiaxes and uitable and there is a noticeable lag while hiding or showing the grid. The lag is mostlty comming from 'clipping' and resizing the axes or table (do not confuse with axes clipping property!)
I tried to hide the grid childred while folding (setting RowHeight(i) = {0}) or unhide while unfolding (RowHeight(i) = {'2x'}) but it doesnt seems to bring any visual improvement for the app
Thanks!
Mario Malic
Mario Malic on 29 Oct 2020
Edited: Mario Malic on 29 Oct 2020
It still is an issue, and is probably being fixed. My issue is with 3D rotation, it takes around 3-7 seconds to even start moving. I have attached code and variables to test.
In 2020b it is still an issue.
How do I use the UIFIGURE/AXES combination?
I tried to use:
app.AX=axes('parent',app.UIFigure);
in the startup function, and then plot in app.AX, it is not faster than the UIAXES generated by app designer, and the FIGURE/AXES combination is still at least 7 times faster.
Veronica Taurino
Veronica Taurino on 2 Mar 2021
Edited: Veronica Taurino on 2 Mar 2021
@Alberto Lutman could I ask if you solved the speed trouble? (I am using UIFIGURE/AXES on app Design, but it is too slow compared with figure/axes)
@Chris Portal how did you reach those speeds (compared with UIFIGURE/UIAXES)?
  • UIFIGURE/AXES: Elapsed time is 0.205658 seconds.
I had no improvements on speeds, but maybe I'm doing something wrong. I'm using something like this:
function startupFcn(app)
uif=app.UIFIGURE;
app.AX=axes('parent',uif);
title(app.AX,'PROVA')
app.AX.Position=[0.05 0.1100 0.9 0.80];
end
but my plot is very slow (I'm using plot3, I need to plot point clouds and both pcshow and scatter3 have problem in app Design).
@Veronica Taurino I was not able to fix the speed issue within app designer. My work around has been having the slow part written with app-designer while plots are on a separate figure that has regular axes in it.
There are other speed-related problem even with this solution, and this is the code I use to make the axes "ASSE"
app.PGR=figure
app.ASSE=axes(app.PGR,'Position',[0.13,0.1,0.7750,0.8150]);
app.ASSE.Interactions=[];app.ASSE.Toolbar=[];
app.PGR.MenuBar='none'; app.PGR.ToolBar='none';
app.ASSE.NextPlot='replacechildren';
The additional lines help with other speed problems, like extreme slow down when mouse hoovers on the figure or hoovers over data inside the figure.
And if I can push the app designer problem of speed further, also displaying formatted tables output is problematic, the label component is fast, but it is difficult to display its string into formatted output because it has no latex interpreter. Tables would be very well formatted, and I always used them in Guide, but in app designer are so slow that are not usable to display a changing output. I ended up using annotation in the figure app.PGR, where you can set as string a latex array and set the interpreter to latex for formatted output. Just don't make a new annotation every time, but replace the string.
@Chris Portal No, axes instead of uiaxes are not faster. Just tried it out and the result was literally exactly as slow as uiaxes. Maybe delete your answer - I just spent 20 minutes rewriting my code for nothing.
@Alexander Kramlich, check out the data shared in the comment section under the main question. It shows considerable and consistent time differences between uifigure/uiaxes vs regular figures/axes in R2020b and R2021a.
Always test things like that before sinking time into implementing something that may not solve the problem. The comments I mentioned above also contain m-files that you could simply download and run to test the timing on your system.
If you saw no difference in run time between axes and uiaxes that indicates that the bottleneck you are observing is due to some other part of your code unrelated to axes generation. I'm also curious how you compared the run time between the two version of your code. Presumably you now have two version of your code that use axes() or uiaxes() and you can compare their run time using tic/toc or by running the Matlab profile report on each of them.
Here we are in 2023 and no updates?
This difference was found in 2020 and until now it is impossible to iterate/rotate with my figure if it is in the GUI.
Does anyone know if this is fixed in v2023a?
Lmao doesn't seem like it. Stlil super slow for me
Testing on 2023b, and the issue is still present. No matter what I try, any axes I add to AppDesigner, no matter the method, updates atleast 5x slower then doing that same update with figure. There is a slight improvement to switch to axes instead of UIAxes though it is not nearly enough for what I am trying to do.
Florent
Florent on 23 Nov 2023
"these UIAXES/AXES differences will soon become a much simpler story with some up and coming work. Keep an eye out for the MATLAB release notes!"
--> Would it be possible to have more details on this in 2023 ?
Using 2023b, UIAxes / Axes can not be used in AppDesigner because it's super slow. This prevents me from migrating an entire application to app designer, since the test teams prefer the original application and don't consider the new one usable.
I am also having issues with very slow panning on axes created within AppDesigner. I haven't had these issues when creating axes within GUIDE. Perhaps this is why MATLAB still keeps GUIDE around? @Adam Danz, can you hint if there is any fix coming to AppDesigner in the near future? Thank you.
@Ford Creighton, could you share some reproduction steps to recreate whatever is in your app's axes? Also, what MATLAB release you're using? I'd like to see what you're seeing and test it across releases.
Just FYI, my comments in this thread prior to Feb 2022 were from before I worked at MathWorks.
Ford Creighton
Ford Creighton on 14 Dec 2023
Edited: Ford Creighton on 14 Dec 2023
@Adam Danz, this is part of a larger application with several parts, but recreating the issue within RealtimeDataDisplay.mlapp. ("RDD"), which is attached, shows the issue enough to diagnose.
Within RDD, there are 4 separate axes all with linked datetime X-axes. This was necessary because we're unaware of a way to have a clean plot with multiple left Y-axes - all with different YLims. If you know of a clean way to do this, please advise. Also, we prefer not to scale the data and plot it all on the same axis, or use yyaxis right (input from end users). Within RDD, any panning of the axes causes several seconds of delay in other functions that are being run at the same time - a delay length which is undesireable. This delay seems to be independent of the amount of data that's been plotted, as it occurs without any data on the plots. Since my last post, we've tested having the user input the Y-limits via an edit field that pops up when "Adjust Axis" button is pushed. This seems to work quickly, and might suffice in the short term, though it isn't ideal. We'll probably short-term implement this for the X-axis as well, but again, if there's a solution to speed up the panning and zooming, that would be ideal.
We ran the profiler while panning, and with the newest update of user-input YLims. The delay appears to be coming from the builtin MATLAB function validateAndSetLimits, and within that, line 28 (drawnow update;), and the child "DatetimeRuler>DatetimeRuler.doChooseMajorTickValues". The parent of validateAndSetLimits is "PanInteraction>PanInteraction.dragprogress". It seems panning on the linked Datetime x-axes are trying to update frequently while panning, and this is causing the lag. Is there a way to pause axis-limit updates when the Panning tool is selected and a buttonDownClick event occurs, and then update the axis limits after a buttonUpClick event occurs?
------------------------------------------------------------------
MATLAB Version: 9.12.0.1975300 (R2022a) Update 3
Operating System: Microsoft Windows 10 Enterprise Version 10.0 (Build 19044)
Java Version: Java 1.8.0_202-b08 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
MATLAB Version 9.12 (R2022a)
Data Acquisition Toolbox Version 4.5 (R2022a)
Image Processing Toolbox Version 11.5 (R2022a)
Instrument Control Toolbox Version 4.6 (R2022a)
MATLAB Compiler Version 8.4 (R2022a)
Signal Processing Toolbox Version 9.0 (R2022a)
Statistics and Machine Learning Toolbox Version 12.3 (R2022a)
Adam Danz
Adam Danz on 18 Dec 2023
Edited: Adam Danz on 19 Dec 2023
Thanks for the info and files @Ford Creighton. The example app you provided is very helpful and we were able to reproduce the slow panning response you described. I tried replacing linkaxes with LimitsChangedFcn and with a listener for each axes but neither alternative solved the problem.
One improvement made in R023b is that axes interactions are optimized for linked axes that share the same container. We're working on extending this to linked axes in different containers. To test this, I moved your axes out of the tab group and into the grid layout in R2023b and confirmed a smoother pan interaction but with some additional room for improvement on our end.
> Is there a way to pause axis-limit updates when the Panning...
The complication with this customized interaction is that when the figure is assigned a WindowButtonUpFcn, default panning is suppressed in the axes. You can turn on panning via the axes toolbar but doing so suppresses the WindowButtonDown/up function assigned to the figure.
Thanks for sharing the profiler results - I've forwarded that info to the right people.
To anyone else having issues, it's extremely helpful to share your release info and to supply an example that reproduces the problem as Ford Creighton has done.
Thanks for the reply @Adam Danz. From what I gather, removing the tabs in the app and placing all 4 axes on a single container/app-page will speed up the linked axes panning in 2023b?
If so, I will work on migrating to 2023b in the next month or so and set a reminder to follow up here with results.
> removing the tabs in the app and placing all 4 axes on a single container/app-page will speed up the linked axes panning in 2023b?
Yes, I did just that and tested it in R2023b to confirm considerable improvements in performance during panning.

Sign in to comment.

More Answers (3)

Matlab User
Matlab User on 21 Mar 2021
Edited: Matlab User on 21 Mar 2021
I just installed Matlab R2021a and this is still not resolved - the jaw dropping UIAxis lag is still there. Maybe it was a mistake to fork Guide into a new thing...
@Chris Portal It seems no-one can reproduce your solution. Are you sure that you did not simply time FIGURE/AXES twice? Could you please share your code if it works for you.
I'm using some code like below (not full):
ax_id = app.UIAxes;
an = animatedline(ax_id, 'MaximumNumPoints',1000);
...
for i=1:1:100000
addpoints(an, x(i), y(i));
if (rem(i,100) == 0)
if i>=1000
xlim (ax_id, [i-1000+1 i]);
else
xlim (ax_id, [1 i]);
end
drawnow limitrate
end
end
Here are some timings:
  • No plotting: 60s
  • Standard Figure + axes: 63s
  • UIaxes only: 84s
I hope this will be resolved in the future - many many threads with complaints, but nothing has been done.
Veronica Taurino
Veronica Taurino on 2 May 2022

1 vote

Are there any speed-improvements in Matlab 2021b? If so, I still struggle to find it by myself
martin nguyen
martin nguyen on 5 Dec 2023
Edited: martin nguyen on 5 Dec 2023

0 votes

Hello everybody,
I have found a way to improve the speed of interactions with a uifigure/uiaxe application. This is not optimal but for me, it does the trick. The solution is to open a figure very small at the start of the application. The figure is in the left bottom corner of my application and I can minimize it (it is working minimized or not).
And all you have to do is to make sure that the figure remains while you are on your application. I did a bit of code to make sure the figure cannot be deleted by clicking on the cross and I make sure it is deleted when I close the application. In my application, I display meshes and the interactions with the pointer are now far better with the figure opened.
I guess, when I open the figure, the uifigure inherit some properties of the figure and that could be the reason, this is faster but I'm not sure.
Regards
Martin Nguyen

2 Comments

Let me see if I understand correctly. Does your issue improve if you have another figure open? Here's a video of my application, and you can see that even with another figure open, the response time still remains very slow.
martin nguyen
martin nguyen on 7 Dec 2023
Edited: martin nguyen on 7 Dec 2023
Hello,
Yes but I create my figure in the startup function of my application, I don't know if you did this or you opened a figure from the Matlab console. Because when my app is running and I open a figure from the Matlab console it doesn't work, it has to be launched within the app. I create and open the figure in the startup function of my app then I minimized it and it works, the response time on my uiaxes in my app are far better.

Sign in to comment.

Categories

Find more on Graphics Performance in Help Center and File Exchange

Products

Release

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!