An Efficient way of generating a legend for 'for loops plots'

5 views (last 30 days)
Dear all,
I wrote a matlab code to plot various data from a FEM analysis. My problem is creating a legend efficiently. The code uses for loops to plot an different objects multiple times. If i do not specify the objects clearly, the legend function will see thousands of different graphic objects. For this reason my code does something similar to this:
for i = 1 : n
h = plot3(variable(i, 1), variable(i, 2), variable(i, 3));
end
legend(h, 'myvariable')
(the only difference is that h actually stores the information from different lines/data, it is a vector of handles).
The thing i do not like is that i am saving the information about my graphic object multiple time. I have not tested this but i think is clear it will increase the overall plotting time (the amount of data i am plotting can be really large). My solution to this was the following:
h = 0;
for i = 1 : n
if h == 0
h = plot3(variable(i, 1), variable(i, 2), variable(i, 3));
else
plot3(variable(i, 1), variable(i, 2), variable(i, 3));
end
end
legend(h, 'myvariable')
This is likely to work but it will double the length of my code that right now is already 540 lines. Honestly i prefer a compact code, hence my questions: is there any other solution apart from the one I proposed? does anybody have any idea on how i can solve this problem? Am i doing it right?
Thank you!
(PS note: the for loops are necessary, i need to plot line segments which are not connected to each other)
  5 Comments
Lorenzo Chiaverini
Lorenzo Chiaverini on 31 Mar 2021
Edited: Lorenzo Chiaverini on 31 Mar 2021
yes, (it is already pretty slow and i was trying to optimise it)
Jan de Jong
Jan de Jong on 31 Mar 2021
One way of avoiding a multitude of line segments you could store the variables into a single vector interleaved with nans.
var1 = randn(6,3);var2 = randn(6,3);
mastervar = [var1;nan(1,3);var2];
plot3(mastervar(:,1),mastervar(:,2),mastervar(:,3))
I do not think storing handle h to your plot will increase the computational burden. It is just a link.

Sign in to comment.

Accepted Answer

Steven Lord
Steven Lord on 31 Mar 2021
Two suggestions:
1) When you create the graphics object, set its DisplayName property. Then when you want to show the legend, you won't have to specify the names.
x = 0:360;
axis([0 360 -1 1])
hold on
h = gobjects(1, 2);
h(1) = plot(x, sind(x), 'DisplayName', 'sine');
h(2) = plot(x, cosd(x), 'DisplayName', 'cosine');
legend
% or to show just one
legend(h(2))
2) If the lines that you're drawing are all part of the same "thing", rather than creating a lot of small (2 point) line objects you can include NaN values in your data to be plotted to break the line at that point.
figure
x = 1:15;
x(mod(x, 3) == 0) = NaN;
h = plot(x, x)
h =
Line with properties: Color: [0 0.4470 0.7410] LineStyle: '-' LineWidth: 0.5000 Marker: 'none' MarkerSize: 6 MarkerFaceColor: 'none' XData: [1 2 NaN 4 5 NaN 7 8 NaN 10 11 NaN 13 14 NaN] YData: [1 2 NaN 4 5 NaN 7 8 NaN 10 11 NaN 13 14 NaN] ZData: [1×0 double] Show all properties
5 line segments visually, but just one graphics object in memory.
  4 Comments
Lorenzo Chiaverini
Lorenzo Chiaverini on 1 Apr 2021
I see, that is great. Yes i am adding arrows in a loop, i will try to preallocate the object as you said and see what happens. Thank you!
Lorenzo Chiaverini
Lorenzo Chiaverini on 10 Apr 2021
Just to let everybody interested know, now the plotting time is a way faster, from 200s to about 10. Thank you again.

Sign in to comment.

More Answers (0)

Categories

Find more on Graphics Object Properties in Help Center and File Exchange

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!