MATLAB: How to plot data from cell array based on a logical array

cell arraysMATLABplotting

I started with the manual code below to plot five lines of data:
% code




xAxis = 1:numel(plotLine1);
myPlot = plot(xAxis,plotLine1(:)','k',...
xAxis,plotLine2(:)','b',...
xAxis,plotLine3(:)','c',...
xAxis,plotLine4(:)','m',...
xAxis,plotLine5(:)','g','LineWidth', 0.5)
But I want to select which data to plot based on a function output. The function populates the data into plotLine(n) and also returns a "logical" 1×5 cell array (1 for "yes", 0 for "no"), which is used to select, from plotData, which lines of data will be plotted. The logical array can contain any possible combination of the five data sets. Since each data has its own color defined, plotLine1 will always contains the data Ch01, plotLine2 the Ch06 and so on. Then I use plotData with the "logical" array to find out which data will be plotted.
% code
plotData(1,1) = {'xAxis,plotLine1(:),''k'''};
plotData(1,2) = {'xAxis,plotLine2(:),''b'''};
plotData(1,3) = {'xAxis,plotLine3(:),''c'''};
plotData(1,4) = {'xAxis,plotLine4(:),''g'''};
plotData(1,5) = {'xAxis,plotLine5(:),''m'''};
ri = 1;
for r=1:5
a=logicArray(1,r);
bitTest = str2num(a{:});
switch bitTest
case 1
plotContents(1,ri) = {plotData(1,r)};
ri = ri + 1;
end
end
plotData only holds the references to the data (plotLine = 18000×40 double, that is loaded with the necessary data in the function).
I have tried concatenating plotContents:
% code
toPlot = '';
for r = 1:numel(plotContents)
if r < numel(plotContents)
toPlot = strcat(toPlot,plotContents{1,r},',');
else
toPlot = strcat(toPlot,plotContents{1,r});
end
end
finalPlot = toPlot{:};
myPlot = plot(finalPlot,'LineWidth', 0.5)
But it gives the error: "Error using plot Invalid first data argument.
Error in PlotViewer_function (line 234) myPlot = plot(finalPlot,'LineWidth', 0.5)"
I have also tried:
% code
hold on
cellfun(@(x) plot(x), plotContents);
Error code: "Error using plot Invalid first data argument
Error in PlotViewer_function>@(x)plot(x) (line 233) cellfun(@(x) plot(x), plotContents);"
I have also tried:
% code
finalPlot = strcat(toPlot{:},',''LineWidth'', 0.5');
myPlot = plot(finalPlot)
where finalPlot is a 1×85 char containing (in one example): xAxis,plotLine1(:),'k',xAxis,plotLine3(:),'c',xAxis,plotLine5(:),'m','LineWidth', 0.5
The error it gives: "Error using plot Invalid first data argument.
Error in PlotViewer_function (line 236) myPlot = plot(finalPlot) "
How can I plot the selected data using plotLine(n) and the logical array?

Best Answer

Far too complex.
You are trying to define strings which will be magically evaluated and converted back into data. The syntax you invented (passing character vectors/strings to the plot function) simply does not work. Did you see this in the plot documentation? This could be made to work, but it would be a very slow, complex, obfuscated, and buggy way to write code. Read this to know why:
You also throw away most of your strings here anyway:
finalPlot = toPlot{:};
Method One: comma-separate list: there is no reason why you need to use strings at all. Why bother? Just put all of the numeric data into a cell array and then use a comma-separated list when calling plot. First lets define some sample data:
>> N = 7;
>> Y = randi(9,N,5)
Y =
8 7 8 2 5
5 2 7 8 2
6 3 9 9 9
4 9 6 9 8
3 8 1 7 9
2 7 4 4 1
3 6 1 4 5
>> X = linspace(0,1,N);
and then select which data to plot using the logical index idx:
C = num2cell(Y,1);
C = repmat(C,3,1);
C(1,:) = {X};
C(3,:) = {'k','b','c','g','m'};
idx = [true,true,false,false,true];
plot(C{:,idx}) % comma-separated list
Method two: basic indexing: here is an another solution using basic MATLAB indexing and NaN's (which are not plotted). The same columns will always have the same color, regardless of which columns you plot.
>> plot(X(:),Y+(0./idx))
>> legend('L1','L2','L3','L4','L5')
Just change the index vector and you will get only those columns that you request:
>> idx = [false,true,false,true,false];
>> plot(X(:),Y+(0./idx))
>> legend('L1','L2','L3','L4','L5')
To make this work for your situation just need to concatenate those vectors into one matrix (which they should be already):
Y = [plotLine1(:),plotLine2(:),plotLine3(:),plotLine4(:),plotLine5(:)];
and define the index something like this (not that str2num is best avoided):
idx = str2double(a)==1;
You can change the color by setting the axes' line ColorOrder property.