Legend in Matlab Plotting - matlab

I have some issues with the legends. I am trying to plot using this code and the code is this:
function PlotNormalPlot(z,i)
hold on
plotTypes = {'b', 'm', 'c'};
TrancheRange = {'100','1000','10000'};
h = normplot(z);
set(h,'color',plotTypes{i})
xlabel('Estimate')
ylabel('Probability')
legendInfo{i} = TrancheRange{i};
legend(legendInfo);
end
It is giving me this error:
Error using legend>process_inputs (line 552)
Cell array argument must be a cell array of strings.
Not sure why this error is there? Need some guidance.
EDIT:
When i tried this:
function PlotNormalPlot(z,i)
hold on
plotTypes = {'b', 'm', 'c'};
TrancheRange = {'100','1000','10000'};
h = normplot(z);
set(h,'color',plotTypes{i})
xlabel('Estimate')
ylabel('Probability')
%legendInfo = TrancheRange{i};
legend(TrancheRange);
end
The legend came out well but the color doesn't get attached to the legend. Not sure why.
Looks like this now:

Try legendInfo=TrancheRange{i}, so legendInfo is a single string.
legendInfo{i} will create a cell array, and, for i=2 as an example, would give you legendInfo={[] '2'} where the first element of legendInfo is an empty array.
I think this could answer your second question. It saves the legend information with the plot handle:
h = normplot(z);
set(h,'color',plotTypes{i},'DisplayName',TrancheRange{i})
legend(h,'show')

Related

Is there a way to give different titles to MATLAB figures being plotted inside a loop?

I am struggling to get different titles in each of my plots, below is my code and the error I keep getting:
code:
figure(5)
tiledlayout(2,3)
titles = ['0.1mm' '1mm' '2mm' '3mm' '4mm' '5mm'];
for i=1:length(L_PsiI1)
Psi_array2 = L_PsiI1(i)*I_array;
nexttile
plot(I_array, Psi_array2)
xlabel('Current (A)')
ylabel('Flux (Wb)')
grid on
title(titles(i))
end
error:
Index exceeds the number of array elements (14).
The code works perfectly fine when I comment out the title(titles(i)) line. I have also tried methods such as title(['Psi-I diagram ' num2str(i)]) and title(sprintf('Psi-I diagram %d',i)) as suggested by others. Many thanks to anyone who can help.
Convert the titles matrix to a cell by replacing the square brackets with curly brackets.
figure(5)
tiledlayout(2,3)
titles = {'0.1mm' '1mm' '2mm' '3mm' '4mm' '5mm'};
for i=1:6
%Psi_array2 = L_PsiI1(i)*I_array;
nexttile
plot([1:10], [1:10])
xlabel('Current (A)')
ylabel('Flux (Wb)')
grid on
title(titles(i))
end

Not enough input arguments for CDF

I am trying to plot a CDF for my data, but I get the following error message:
Error using cdf (line 69) Not enough input arguments
My code:
data =cell(1,5);
for j=1:length(container)-7
data{j} = some_values;
cdfplot(data)
So data is a 1x5 cell while inside of it, the values are the following
1x14600double, 1x260double, 1x2222double, 1x3000double, 1x72double
I am expecting a separate line for each of the double arrays i.e. my cdf figure to have 5 lines.
But, the error message confuses me, since I definitely have passed data. Any ideas?
Edited: ok, I have misswritten instead of cdfplot(), I had cdf()... the problem stays the same
The problem was the lack of knowledge on how cells and figures work.
figure;
hold on;
cellfun(#cdfplot,data);
This code did the job :)
In addition to the OP's answer using cellfun, you can also solve this by adjusting how you access the cell array.
Key Idea: Access A with A{} versus A()
% MATLAB R2018b
% Sample data
A = {rand(1,14600) rand(1,260) rand(1,2222) rand(1,3000) rand(1,72)};
Notice that A(1) returns
ans = 1×1 cell array {1×14600 double}
while A{1} returns the full 1x14600 double array (extracts it completely from the cell array).
% Example usage
szA = size(A);
for k = 1:szA(2)
subplot(5,1,k)
cdfplot(A{k})
end
From this example you can see cdfplot works fine.

Plot several lines (looping through line styles in cell array) in Matlab

I have written this loop to plot each line of results and I get the error message
Error using plot. Invalid first data argument.
So far it looks like this
test=rand(5,6);
xint=[1:1:6];
LineSpec = {'-y', '--m', ':c', '-r.', '-b', ':s'};
for ii=1:5,
plot(xint,test(ii,:),LineSpec(ii),'linewidth',2);
hold on;
legend_str{ii} = num2str(ii);
end
If I use plot(xint,test(ii,:),'-y','linewidth',2) then it works. But how can I avoid the error when looping through line styles?
You should write:
plot(xint,test(ii,:),...
LineSpec{ii},...
'linewidth',2);
LineSpec is a cell array, so LineSpec(ii) returns a cell, while plot asks for a character array as line properties.
you can see the difference when you call LineSpec:
>> LineSpec{1}
ans =
-y
>> LineSpec(1)
ans =
'-y'
When the output is a cell then the answer is indented and has the single-quote marks.

subplots for a combination of cell arrays

I am attempting to generate a figure with several subplots, e.g.
time = 1:365;
data = {rand(365,1),rand(365,1),rand(365,1)};
data2 = {rand(365,1),rand(365,1),rand(365,1)};
figure(1);
for i = 1:length(data);
for ii = 1:2:2*length(data);
for jj = 2:2:2*length(data);
subplot(5,2,ii);
plot(time,data{i});
subplot(5,2,jj);
plot(time,data2{i});
end
end
end
From this code I was trying to generate a subplot for each cell in 'data' and 'data2' where each of the cells in 'data' were plotted in subplots 1,3,5 and those in 'data2' in subplots 2,4,6. The code that I generate reproduces the same figure in all of the subplots for data and data2 instead of what I described above. I'm guessing the problem here is that the number of cells in each data set is 3 and the loop runs over 6 iterations? How can i fix this?
Try this. You don't need this nested loop there...
figure(1);
for i = 1:length(data);
subplot(5,2,(i-1)*2+1);
plot(time,data{i});
subplot(5,2,(i-1)*2+2);
plot(time,data2{i});
end

How to write this in an elegant way (cell arrays and structs in MATLAB)

I would like to plot connected points in MATLAB.
My connected points come from connecting objects of "stats", where each "stat" comes from a BW regionprops struct.
The code I have written works, but it suffers from a lot of "ugliness", which I couldnt fix even after trying various ways.
function plot_line( line )
a = cell2mat(line);
b = {a.Centroid};
matx = {};
maty = {};
for i = 1:size(b,2)
matx{end+1} = b{i}(1);
maty{end+1} = b{i}(2);
end
plot ( cell2mat(matx), cell2mat(maty) );
end
Can you help me make this code nicer? It's not critical, as my code works fine and as the lines are short (<100 points) the performance is not an issue.
It is just that it would be really nice to know how this tiny function should be written in the proper way, without for loops and 3 calls of cell2mat.
In my example:
line is a <1xn cell>,
line{1} has a property 'Centroid' and
line{i}.Centroid(1) are the x coordinates and
line{i}.Centroid(2) are the y coordinates.
Actually, all I need is plotting line{i}.Centroid(1), line{i}.Centroid(2) for i = 1:size(line,2), but I don't know how.
Instead of creating a cell array b, you can create a numerical array directly, by catenating using CAT:
tmp = cat(1,line{:});
coordinates = cat(1,tmp.Centroid);
plot(coordinates(:,1),coordinates(:,2))
EDIT
If you want to keep it really short (i.e. even shorter than #Amro's solution you can use CELLFUN like this in order get a one-liner:
plot(cellfun(#(x)x.Centroid(1),line),cellfun(#(x)x.Centroid(2),line))
Example:
line = repmat({struct('Centroid',[1 2])},1,5); %# similar to the data you have
%# extract x/y coordinates
x = cellfun(#(s)s.Centroid(1),line)
y = cellfun(#(s)s.Centroid(2),line)
%# plot
plot(x,y)
You could also do it as:
xy = cell2mat(cellfun(#(s)s.Centroid, line, 'UniformOutput',false)');
plot(xy(:,1),xy(:,2))