Matlab Link data for a line graph on a scatter plot - matlab

I have a line which is plotted on another scatter plot. This line changes its shape from time to time. Is there any way by which I can specify in my program that the data for drawing this line is dynamic so that the plot updates by itself when the data changes?
Now what I am doing is draw the entire figure again after each data update. The program has very large number of iterations(>5000) and I need to visualize every change. That means figure should be drawn 5000 times. This is making my program very slow. Is there any other better way of doing this?

The refreshdata function might do what you want.

To automatically update a graph when a source variable changes, use the linkdata function. MathWorks has a is a great introduction page. However, there is a short example in the documentation:
x = [1:20];
y = rand(20,3);
area(x,y)
linkdata on
Then you can change a variable and the plot automatically redraws:
y(10,:) = 0;
Automatic update.
Note: Changing the source to a different variable entirely is a different thing. If YDataSource is reassigned, then refreshdata would be needed, as pointed out by Molly. Otherwise, this will keep your plot up-to-date when the variable changes.
One caveat is described on this page:
linkdata buffers updates to data and dispatches them to plots at roughly half-second intervals. This makes data linking not suitable for smoothly animating changes in data values unless they are updated in loops that are forced to execute two times per second or less.

Related

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.
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. 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');
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.
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?
Furthermore I wonder if it is known why legend in general is so slow and has such odd behavior.
Purpose
I'm adding some information here to avoid the XY Problem.
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. 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. 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.
data2, which toggles the visibility of both the data2, and linear model 2 data lines.
linear model, which toggles the visibility of the linear model 1, and linear model 2 data lines.
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.
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.
My current working approach instead manually sets the DisplayNameproperty of all lines and then the button callbacks adjust each lines Annotation.LegendInformation.IconDisplayStyle property. According to the documentation the user then needs to call legend to force an update.
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. Therefore I'm forced to call 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. I've already ensured that my code runs 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. Thereby doing what the MATHWORKS documentation claims to be implemented (although it is not) in 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. 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.

Matlab imshow update image at old position and magnification

I currently use Matlab's imshow to output an image at every iteration of a diffusion filter process, i.e. multiple times per second.
Sometimes during filtering I want a closer look at specific image parts.
However, when using the ('Parent', handle) name-value pair for imshow the magnification and position gets reset.
Is there a way to update the underlying image but having the magnification and position intact?
You can update the cdata in the current axis to your new data matrix which will keep all other settings the same. If this is in a loop, you probably need to call drawnow. E.g:
x=randn(100);
figure;imagesc(x);
Now zoom / pan / do whatever manipulations you want.
f=gca;
x=randn(100);
f.Children.CData = x;
This method of updating of child data is recommended by Matlab as more efficient than destroying the axis child Image and recreating each frame (can't remember the source, it was in one of the help files).
Edit: Just remembered that this syntax won't work on older versions of matlab (pre 2015 or so). In that case, use get/set syntax:
set(get(gca,'Children'),'CData',x);

Matlab: linkaxes squeezes my graph

I have drown several graphs thanks to "subplot" function on MatLab and it works well.
Nevertheless, I want all my graphs to have the same Y-scale so that I can compare them.
I used the "linkaxes" function and my all my graphs have the same scale but the problem is that some of my figures are "beheaded", lacking their upper part, or one of my figures is completely squeezed.
I don't get what happened. Could you please help me to solve the problem or tell me about another function that would be more appropriate in my case?
Here's part of my code:
for i=1:1:9
m=n(i);
fichier=sprintf('%d.txt',m);
M=load(fichier);
z=length(M(:,1));
x=M(1:z,1);
y=M(1:z,2);
a(i)=subplot(2,4,i)
contour3=plot(x,y)
linkaxes(a,'y')
end
linkaxes creates a permanent link between the scales of several axes, so that you can subsequently perform zoom operations (perhaps interactively) on one, and have the other automatically update.
If you need that functionality, then linkaxes is the right command (although you could possibly also look at linkprops).
However if all you need is to ensure that the y-axis limits of your axes are the same, it will probably be easier (and you will have more control) if you set them directly. You can retrieve the y-axis limits using ylim(axis_handle) and set them using ylim(axis_handle, [lower, upper]), or alternatively with get(axis_handle,'YLim') and set(axis_handle,'YLim',[lower,upper]). You might also look at the YLimMode property of the axis, which determines whether the axis limits are directly set or automatically resized.

Does Matlab execute a callback when a plot is zoomed/resized/redrawn?

In Matlab, I would like to update the data plotted in a set of axes when the user zooms into the plot window. For example, suppose I want to plot a particular function that is defined analytically. I would like to update the plot window with additional data when the user zooms into the traces, so that they can examine the function with arbitrary resolution.
Does Matlab provide hooks to update the data when the view changes? (Or simply when it is redrawn?)
While I have yet to find one generic "redraw" callback to solve this question, I have managed to cobble together a group of four callbacks* that seem to achieve this goal in (almost?) all situations. For a given axes object ax = gca(),
1. Setup the zoom callback function as directed by #Jonas:
set(zoom(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
2. Setup a pan callback function:
set(pan(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
3. Setup a figure resize callback function:
set(getParentFigure(ax),'ResizeFcn',#(x,y) myCallbackFcn(ax));
4. Edit: this one no longer works in R2014b, but is only needed if you add, e.g., a colorbar to the figure (which changes the axis position without changing the figure size or axis zoom/pan). I've not looked for a replacement. Finally, setup an undocumented property listener for the axes position property itself. There is one important trick here: We must hold onto the handle to the handle.listener object as once it's deleted (or leaves scope), it removes the callback. The UserData property of the axes object itself is a nice place to stash it in many cases.
hax = handle(ax);
hprop = findprop(hax,'Position');
h = handle.listener(hax,hprop,'PropertyPostSet',#(x,y) myCallbackFcn(ax));
set(ax,'UserData',h);
In all these cases I've chosen to discard the default callback event arguments and instead capture the axis in question within an anonymous function. I've found this to be much more useful than trying to cope with all the different forms of arguments that propagate through these disparate callback scenarios.
*Also, with so many different callback sources flying around, I find it invaluable to have a recursion check at the beginning of myCallbackFcn to ensure that I don't end up in an infinite loop.
Yes, it does. The ZOOM mode object has the following callbacks:
ButtonDownFilter
ActionPreCallback
ActionPostCallback
The latter two are executed either just before or just after the zoom function. You could set your update function in ActionPostCallback, where you'd update the plot according to the new axes limits (the handle to the axes is passed as the second input argument to the callback).

real time plotting on iPhone using core plot?

I want to use core-plot for drawing line graph dynamically. data won't come at a time, we will be receiving point by point dynamically.
Is it possible to draw the chart dynamically using core-plot i.e drawing point by point as on when we receive the (x,y) point?
Please help me, Thanks.
Yes, you can do this reasonably easily. For each received data point, append it to an array of values to display. As these data points come in, call -reloadData on the Core Plot graph (or just the particular plot) to redraw the graph, passing in the array you just added a value to in response to the -numbersForPlot:field:recordIndexRange: delegate method.
If you need to adjust the plot range to track your data points (for a moving ticker), recalculate the new CPPlotRange for the X axis and set the plot space's xRange property to that.
Use the CPTestApp-iPhone, AAPLot, or StockPlot examples as templates for how to set up the line chart overall, and modify from that starting point.
I do something similar to this on the Mac in a scientific application:
(source: sunsetlakesoftware.com)
Sounds like you could make use of a demo project I put together and wrote about here (not core plot related though).
It draws a EKG graph but should easily be modified to use another input than the repeated "heart beat"...See line 320 in EAGLView.m where the indata is entered into the array.