Is MATLAB the best way to dynamically update a row handles XData and YData?

I collect data and draw this data in real time. Data is created by a motion capture system. I have one DynamicDataset class, which is just a wrapper around a matrix with two columns (although it is thinner) with an event notification for new data; another DynamicPlotter class that listens for an event with data addition and dynamically updates the chart. Relevant code fragments:

 classdef DynamicDataset < handle properties newestData = []; data = [] end events DataAdded end methods function append(obj, val) obj.data(end+1,:) = val; obj.newestData = val; notify(obj, 'DataAdded'); end end end classdef DynamicPlotter < dynamicprops properties FH %# figure handle AH %# axes handle LH %# array of line handles - may have multiple lines on the plot dynProps = {} %# cell array of dynamic property names - %# use to access individual datasets end methods function obj = DynamicPlotter(props) %# props is a cell array of dynamic %# properties to store information for i = 1:length(props) addprop(obj, props{i}); obj.(props{i}) = DynamicDataset; obj.dynProps = [obj.dynProps props{i}]; addlistener(obj.(props{i}), 'DataAdded', @obj.updatePlot(i)); end obj.createBlankPlot(); end function createBlankPlot(obj) obj.FH = figure; obj.AH = axes; hold all; for i = 1:length(obj.dynProps) obj.LH(i) = plot(nan); %# only used to produce a line handle set(obj.LH(i), 'XData', [], 'YData', []); end end function updatePlot(obj, propNum) X = get(obj.LH(propNum), 'XData'); Y = get(obj.LH(propNum), 'YData'); X(end+1) = obj.(dynProps{propNum}).newestData(1); Y(end+1) = obj.(dynProps{propNum}).newestData(2); set(obj.LH(propNum), 'XData', X, 'YData', Y); end end end 

Based on the MATLAB code profile, the set command in updatePlot() pretty expensive. I am wondering if there is a better way to calculate individual points as they become available? Ideally, I would click one point on XData and YData and draw only that point, but I don’t know if this is possible.

Please note that there may be several line objects (for example, several graphs on the same section); plot() takes an axis descriptor as an argument, so it will not consider the properties of previously drawn line descriptors (or is there a way to do this); I was thinking about just doing plot(x,y);hold all; but that would give me separate line handles each time, each of which would correspond to one point.

It may not be possible to make a graph of incoming points faster, but I decided that I would ask.

EDIT . Updated OP with the actual code I'm working with, instead of using a common example for misinterpretation.

+6
source share
3 answers

The amount of data that you process in each update is large (although only one point actually changes), making your code O (N ^ 2).

Using the second row of lines to create a large group of data, you can alternate adding each point to a short “active” line and often adding large blocks to the main lines. Although this does not exactly exclude O (N ^ 2), it can significantly reduce the constant.

If you do, be sure to overlay the "old" lines and the "active" lines on one point so that they connect.

Essentially:

  function updatePlot(obj, propNum) X = get(obj.LHactive(propNum), 'XData'); Y = get(obj.LHactive(propNum), 'YData'); X(end+1) = obj.(dynProps{propNum}).newestData(1); Y(end+1) = obj.(dynProps{propNum}).newestData(2); if numel(X) > 100 Xold = [get(obj.LH(propNum), 'XData'); X(2:end)]; Yold = [get(obj.LH(propNum), 'YData'); Y(2:end)]; set(obj.LH(propNum), 'XData', Xold, 'YData', Yold); X = X(end); Y = Y(end); end set(obj.LHactive(propNum), 'XData', X, 'YData', Y); end 
+4
source

Part of the reason your code can take a lot of time is because you use a for loop to assign variables. Depending on which version of Matlab you are using, this will significantly slow down the process. I suggest using a vector to assign values ​​to your x and y as follows:

 x = 1:1000; y = cosd(x); 

Then you can assign the first points in your data.

 xi = x(1); yi = y(1); 

When plotting, assign an XDataSource and a YDataSource.

 h = plot(xi, yi, 'YDataSource', 'yi', 'XDataSource', 'xi'); 

Now that you are looping to change the values, use refreshdata to update the Xdata and Ydata values. Use the drawow function to refresh the drawing window.

 for k = 2:1000, xi = x(1:k); yi = y(1:k); refreshdata(h, 'caller') drawnow; end 
+1
source

Your code is slow because every time you select all the values ​​that you call updatePlot . Therefore, I would stop only the last item in updatePlot (This is also the problem you were talking about: ideally, I would click one point in XData and YData and draw only that point, t know if this is possible.)

  • add property LH_point_counter

     classdef DynamicPlotter < dynamicprops properties FH %# figure handle AH %# axes handle LH %# cell array of line handles - may have multiple lines on the plot % counter that counts home many points we have for each dynProps LH_point_counter = []; dynProps = {} %# cell array of dynamic property names - %# use to access individual datasets end 
  • change updatePlot

     function updatePlot(obj, propNum) % plot new point new_x = obj.(dynProps{propNum}).newestData(1); new_y = obj.(dynProps{propNum}).newestData(2); new_handle = plot(new_x, new_y); % add new handle to list of handles of this property counter_this_prop = obj.LH_point_counter(propNum); counter_this_prop = counter_this_prop + 1; obj.LH{propNum}(counter_this_prop) = new_handle; % save new counter value obj.LH_point_counter(propNum) = counter_this_prop; end 
+1
source

Source: https://habr.com/ru/post/897295/


All Articles