Populating a Legend Dynamically
33 views (last 30 days)
Show older comments
So I am currently working on a code that imports some excel data from any number of files as well as any number of sheets within the excel file. As such I have a for loop within a for loop to account for a random number of files as well as a random number of sheets. With the data I want to plot the data taken from the files, I want a legend to be dynamically populated with the information as it is going through the loop as it is running. Here is the portion of the code being described:
number_of_files = input('Please enter the number of files you would like to import. ');
xlRange = 'C2:K18';
total_materials = 0;
%For Loop to import the data
for i = 1:number_of_files
[filename, pathname] = uigetfile('*.xlsx');
number_of_materials = input('How many composites are you importing from this file? ');
for j = 1:number_of_materials
sheet = input(['Please input sheet for composite ' num2str(j) ': ']);
data(i,j,:,:) = xlsread(strcat(pathname,filename),sheet,xlRange);
%Declaration of each variable will be made here
temperature(i,j,:) = data(i,j,1,:);
FTU11(i,j,:) = data(i,j,8,:);
FTU33(i,j,:) = data(i,j,10,:);
E11t(i,j,:) = data(i,j,2,:);
loopcounter(i,j) = sheet; %Used Later to determine where the data is at.
end
total_materials = total_materials + number_of_materials; %Used later to establish plots
end
x = 1;
while x <= total_materials
for i = 1:number_of_files
for j = 1:length(loopcounter)
if loopcounter(i,j) == 0
continue
elseif loopcounter(i,j) ~= 0
%To plot, the variables need to be transformed into 1D
temperature_plot(:) = temperature(i,j,:);
FTU11_plot(:) = FTU11(i,j,:);
plot(temperature_plot, FTU11_plot,'o')
xlabel( 'Temperature (F)')
ylabel('FTU11 (Msi)')
title( 'In Plane Tensile Strength vs Temperature')
grid on
box on
xlim([0 4500])
ylim([ 0 80 ])
legendInfo{i,j} =['Composite ' num2str(i) '-' num2str(j)];
%saveas( gcf , 'default signal Y1.tif' , 'tif')
end
end
end
x = x + 1;
end
The error being spit out is:
Operands to the || and && operators must be convertible to logical scalar values.
Error in legend (line 162)
all(isgraphics(args{1})) % legend(children,strings,...)
Error in MaterialDataGraphs (line 65)
hl = legend(legendInfo);
In the particular case being tested, one file has 3 sheets, and the other file has only one sheet, resulting in a legendInfo matrix of:
'Composite 1-1' [] []
'Composite 2-1' 'Composite 2-2' 'Composite 2-3'
Is the error due to {1,2} and {1,3} not being populated? Is there another way of going about this or am I attempting something that MATLAB isn't necessarily capable of?
2 Comments
dpb
on 7 May 2018
I don't see the offending line in the code but you've built a 2D array of labels which doesn't meet the syntax requirements of legend; it expects a cell array of labels as a vector array, one cell per object in the plot (typically line) to be labelled.
It isn't clear what you expect plotted on each axes; as written with what is shown you're only going to get one line per axes; there's no hold on to add to an existing axes and the X,Y arguments to plot() are single vectors, not arrays so there's only one line per call.
Describing what you want the plot to contain might help, plus the complete code that created the error and the run that generated the error in context with the complete error message--context is key.
Answers (1)
Steven Lord
on 8 May 2018
Rather than building a large cell array of names that you pass into legend, I would instead use the DisplayName property of the line objects returned by the plot function.
% Sample data
x = 0:0.1:2*pi;
% Configure the axes
axis([0 2*pi -1 1]);
hold on
% Plot the first curve, y = sin(x), and give it a name to be displayed in the legend
plot(x, sin(x), 'DisplayName', 'sine of x');
% Show the legend
legend show
% Add a second curve, y = cos(x), and give it a name
% Depending on the release you're using, the legend may auto-update
plot(x, cos(x), 'DisplayName', 'cosine of x');
This has another benefit: the only time I even need to think about naming the line is exactly when I create the line. If I wanted to change one of those functions, say from cos(x) to (sin(x)+cos(x))/2, I only need to modify one line of code to change both what gets plotted and the name of what gets plotted. If I want to add a new function, I just have to add one line of code that both plots and names it.
plot(x, (sin(x)+cos(x))/2, 'DisplayName', 'average');
See Also
Categories
Find more on Annotations in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!