Optimized Chart Class for Displaying Variable Number of Lines - MATLAB & Simulink (original) (raw)
This example shows how to optimize a chart class for displaying a variable number of lines. It reuses existing line objects, which can improve the performance of the chart, especially if the number of lines does not change frequently. For a simpler version of this chart without the optimization, see Chart Class with Variable Number of Lines.
The chart displays as many lines as there are columns in the YData
matrix, with circular markers at the local extrema. The following code demonstrates how to:
- Define two properties called
PlotLineArray
andExtremaLine
that store the objects for the lines and the markers, respectively. - Implement a
setup
method that initializes theExtremaLine
object. - Implement an
update
method that gets the size of thePlotLineArray
, and then adds or subtracts objects from that array according to the number of columns inYData
.
To define the class, copy this code into the editor and save it with the name OptimLocalExtremaChart.m
in a writable folder.
classdef OptimLocalExtremaChart < matlab.graphics.chartcontainer.ChartContainer % c = OptimLocalExtremaChart('XData',X,'YData',Y,Name,Value,...) % plots one line with markers at local extrema for every column of matrix Y. % You can also specify the additonal name-value arguments, 'MarkerColor' % and 'MarkerSize'.
properties
XData (:,1) double = NaN
YData (:,:) double = NaN
MarkerColor {validatecolor} = [1 0 0]
MarkerSize (1,1) double = 5
end
properties(Access = private,Transient,NonCopyable)
PlotLineArray (:,1) matlab.graphics.chart.primitive.Line
ExtremaLine (:,1) matlab.graphics.chart.primitive.Line
end
methods(Access = protected)
function setup(obj)
obj.ExtremaLine = matlab.graphics.chart.primitive.Line(...
'Parent', obj.getAxes(), 'Marker', 'o', ...
'MarkerEdgeColor', 'none', 'LineStyle',' none');
end
function update(obj)
% Get the axes
ax = getAxes(obj);
% Create extra lines as needed
p = obj.PlotLineArray;
nPlotLinesNeeded = size(obj.YData, 2);
nPlotLinesHave = numel(p);
for n = nPlotLinesHave+1:nPlotLinesNeeded
p(n) = matlab.graphics.chart.primitive.Line('Parent', ax, ...
'SeriesIndex', n, 'LineWidth', 2);
end
% Update the lines
for n = 1:nPlotLinesNeeded
p(n).XData = obj.XData;
p(n).YData = obj.YData(:,n);
end
% Delete unneeded lines
delete(p((nPlotLinesNeeded+1):numel(p)))
obj.PlotLineArray = p(1:nPlotLinesNeeded);
% Replicate x-coordinate vectors to match size of YData
newx = repmat(obj.XData(:),1,size(obj.YData,2));
% Find local minima and maxima and plot markers
tfmin = islocalmin(obj.YData,1);
tfmax = islocalmax(obj.YData,1);
obj.ExtremaLine.XData = [newx(tfmin); newx(tfmax)];
obj.ExtremaLine.YData = [obj.YData(tfmin); obj.YData(tfmax)];
obj.ExtremaLine.MarkerFaceColor = obj.MarkerColor;
obj.ExtremaLine.MarkerSize = obj.MarkerSize;
% Make sure the extrema are on top
uistack(obj.ExtremaLine, 'top');
end
end
end
After saving the class file, you can create an instance of the chart. For example:
x = linspace(0,2)'; y = cos(5*x)./(1+x.^2); c = OptimLocalExtremaChart('XData',x,'YData',y);
Now, create a for
loop that adds an additional line to the plot at every iteration. The chart object keeps all the existing lines, and adds one additonal line for each i
.
for i=1:10 y = cos(5*x+i)./(1+x.^2); c.YData = [c.YData y]; end