Fast updating of live figures using sliders

I created a simple live script where sliders are used to select two parameters, and then a step response is plotted, which depends on the two parameters. Here is my simple code
wn = 2; % in live script, this is a slider for picking wn
zeta = 0.2; % in live script, this is a slider for picking zeta
s = tf('s');
step(wn^2/(s^2+2*zeta*wn*s+wn^2),5)
The plot is sluggish to update as I move the sliders, and I want it to be more responsive. I used the "Run on: Value changing" option, but there is still a visible lag. I think the bottleneck is due to the figure being re-drawn every time I change the parameters. Is it possible for the live script to modify an existing figure every time a slider is changed? This might involve having one chunk of code that is only run once per section (e.g. create base figure, axes, labels, initial plot) and then every time the slider is moved, only certain components of the plot are modified, thus speeding up rendering.
If it turns out that "step" is actually the bottleneck here, then I'm open to other suggestions --- e.g. pre-computing all the step responses for all possible parameter values and not doing any live computations. I don't really care how long it takes to pre-compute or pre-compile, I just want the end product to be a truly interactive (and instantly updating) figure.

3 Comments

I don't see anything in the documentation how you could use a returned handle to modify the properties. You might indeed have to precompute a grid of values and interpolate from there.
My point is that even if I precompute a grid, simply plotting the data I've already computed in a livescript is too slow. It redraws the figure every time I change the slider. You can change figure properties directly in Matlab e.g. by using something like:
p = plot(x,y)
p.YData = ynew;
this is orders of magnitude faster than redrawing the plot. I want to be able to do this in a live script, but I can't seem to prevent the live script from redrawing everything all the time.
Oh, now I see this, sorry, I don't know about livescript behaviour of figures.

Sign in to comment.

Answers (1)

Hi,
This will return the handle to the curve on the plot. You can use its XData and YData property to update the values quickly.
curve = findall(groot, 'type', 'line', 'Tag', 'Curves')
However, the issue with the Slider is that it can obtain values that are unnecessarry to calculate. While you move your slider, it may obtain a lot of different values between i.e. zeta 1e-7 and 2e-7 which probably won't make a notable difference to the plot. So you should come up with a way how to do it. Maybe you could make wn and zeta vector
zeta = 0:1e-2:5;
wn = 0:1e-2:10;
and when the corresponding slider value is within some tolerance of element, calculate and plot the values .
>> clear
>> tic
wn = 2; % in live script, this is a slider for picking wn
zeta = 0.2; % in live script, this is a slider for picking zeta
s = tf('s');
for ii = 1 : 10
step(wn^2/(s^2+2*zeta*wn*s+wn^2),5);
end
toc
Elapsed time is 2.944663 seconds.
This is interesting
>> tic
wn = 2; % in live script, this is a slider for picking wn
zeta = 0.2; % in live script, this is a slider for picking zeta
s = tf('s');
for ii = 1:10
result = step(wn^2/(s^2+2*zeta*wn*s+wn^2),5);
end
toc
Elapsed time is 0.222970 seconds.
Save the output of step into variable, it makes it a lot faster.
Also, this doesn't account the time into updating the plots which might also be significant.

8 Comments

The sliders are not a problem. You can set the stepsize for each slider as an option; it's not a continuously changing value.
The reason saving the output into a variable is faster in the step function is precisely because when used without an output, it generates a plot. And this takes a lot of time.
On my computer, in a standard Matlab script, here is now long things take (in milliseconds)
  • Create new figure and make a simple plot (e.g. a line with 50 points): 125 ms
  • make the same plot, but overwrite an already existing figure: 7 ms
  • make the same plot by modifying an existing plot by directly changing 'YData': 0.2 ms
When I use a livescript with a slider, each update takes 200 ms. If I replace the step command with y=step(...) and then plot(...) instead, then it becomes 20 ms, which is better. What I would really like is to be able to modify the YData field so that I can get another 100x speedup.
I tried using findall(...) as you suggested, but just calling the findall function once already costs 20 ms.
I also tried using gca and other similar things, but then I run into scope issues... gca has global scope and will find axes from other cells instead. It appears to make a copy and re-draw it anyway, which is not what I want.

If it is in a function, use persistent variable to save the plot handle.

persistent var
 if isempty(var)
    fig = findall... 
end
fig.YData = result;
This doesn't work. I tried "persistent" and also "global" but it appears that immediately after a section block in a live script is executed, all handles are deleted. I tried writing
global p
if isempty(p)
plot(t,y)
else
p.YData = y;
end
But the second time I run the section, it tells me that p is not empty, but it doesn't contain a plot either. It says "p = handle to deleted Line".
Does it have to be a live script? Most of these issues will go away if you use a normal figure instead.
The idea of a live script is appealing because it allows me to mix equations, explanations, code, and interactive figures to create better educational materials (I'm a college professor). Also, it's relatively easy to code.
Having interactive figures is essential, in my opinion. I'm not sure how a normal figure would replace all of this.
Yes, livescripts are convenient for these.
persistent p % persistent is better
if isempty(p)
p = plot(t,y); % you didn't save the handle
else
p.YData = y;
end
I made a small example with the livescript (the attached file) and I think that you wouldn't like how slow it updates, noone would. I don't think that livescripts were made to be that responsive. You could create a button in your livescript:
  • That would create a figure with axes and sliders. Design wise, it doesn't fit so well with the livescript, but I am not sure if there's any other viable alternative for it. Cons: programming the figure, axes, sliders can be a hassle to adjust to different screen resolutions for the component positions. If you want to change the design or anything with the app later, it's an enormous effort to do so.
  • Create an app with App Designer, which is much easier to setup, call the app with the button press in livescript. Cons: some time needed to start the app, additional file for the app. Performance is better than in livescript and but still way behind compared to pure figure-based app. See GIF attached as well, this is in App Designer.
I think you're on to something --- I think your example does what I want. The only issue is that it creates a second copy of the figure when I run the whole script (first cell makes the figure, second cell makes a copy and modifies it dynamically). Can you think of a way to create the first figure "silently" so it doesn't display, and then only reveal it when the second cell is run?
also re: your comment "you didn't save the handle". I thought p = plot(...) would save the handle as p? How then should I save p if not this way?
Thanks!
The livescript behavior is weird, in the example, two plots are shown, but in fact, there is only a single plot handle. When the properties of the graphic object change, output will be captured, resulting in another plot being shown. I have tried hiding the visibility of the figure, but then no output will be shown when the slider value is changed. I don't know how to do it, or if if it's possible.
In this comment plot handle wasn't saved, so I thought it didn't work because of that.

Sign in to comment.

Categories

Find more on Graphics Performance in Help Center and File Exchange

Products

Release

R2020b

Asked:

on 4 Jun 2021

Commented:

on 6 Jun 2021

Community Treasure Hunt

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

Start Hunting!