Change marker size in legends of already plotted figures

61 Ansichten (letzte 30 Tage)
MatteP
MatteP am 10 Mai 2019
Bearbeitet: Elizabeth Case am 19 Aug. 2021
Hi everyone,
I do not know why but whenever I save some plots in .fig format from Matlab, the size of the markers of the legend is always changed. That means that, if I open again the .fig file in Matlab, the size of the marker is just set to a default (tiny) size.
I know how to change the marker size in plotting phase, but I do not know how to access it again in already plotted figures.
I tried accessing the handle of the legend with
hLegend = findobj(gcf, 'Type', 'Legend')
and then trying accessing the children of type 'line' to then change the 'Markersize' (as explained here https://stackoverflow.com/questions/28741747/change-the-symbols-size-in-matlab-legend)
ch = findobj(get(hLegend,'children'), 'type', 'line');
but I fail in doing this as there is no this kind of 'Children'.
Any suggestion please?
Thanks and best regards

Antworten (3)

per isakson
per isakson am 10 Mai 2019
Bearbeitet: per isakson am 11 Mai 2019
Short answer: The behavior described in the stackoverflow thread is based on an undocumented feature.
I've reproduce your observations with the following script, which is based on the stackoverflow thread.
%%
plot(1:10, 'o-');
hold on
plot(5:12, 'r*--'); %// example plots
[ lgd, objh ] = legend({'one plot', 'another plot'}, 'location', 'NorthWest', 'Fontsize', 14);
%% // set font size as desired
objhl = findobj( objh, 'type', 'line' ); %// objects of legend of type line
set( objhl, 'Markersize', 18 ); %// set marker size as desired
%%
savefig('matte.fig');
delete( gcf )
%%
openfig('matte.fig')
I use R2018b. The syntax used to call legend with two output arguments, [ lgd, objh ] = legend(___), is not documented. Neither is it documented in R2019a.
Furthermore, I found these two lines in legend.m
% Legend no longer supports more than one output argument
% Warn the user and ignore additional output arguments.
objh used in the stackoverflow thread is not a legend object.
>> lgd
lgd =
Legend (one plot, another plot) with properties:
String: {'one plot' 'another plot'}
Location: 'northwest'
Orientation: 'vertical'
FontSize: 14
Position: [0.1494 0.7758 0.2679 0.1250]
Units: 'normalized'
Show all properties
>> objh
objh =
6×1 graphics array:
Text (one plot)
Text (another plot)
Line (one plot)
Line (one plot)
Line (another plot)
Line (another plot)
Maybe undocumentedmatlab has something to say on this. I found this comment
[...] For some reason, when I save the figure as a .fig, the legend title isn’t saved.
My guess:
  • savefig doesn't save the legend
  • openfig creates a default legend (How does it know it should do that?)
  2 Kommentare
MatteP
MatteP am 12 Mai 2019
Thanks for your reply.
So I guess there is no solution so far, except re-running the script to plot figures again, using the undocumented feature reported in stackoverflow.
What is even more bizzare is that once I open the figure .fig, I am able to retrieve (and edit) the entries of the legend, their fontsize, the marker shape but not marker size.
Best regards,
MatteP
per isakson
per isakson am 17 Mai 2019
Bearbeitet: per isakson am 17 Mai 2019
"even more bizzare" By design Matlab exposes a limited number of properties to the user. In this case fontsize, but not markersize.
[...] Starting in R2014b, graphics handles are object handles of various types, depending on the class of the graphics object. Graphics objects now behave like other MATLAB® objects.
See Save and Load Process for Objects although "behave like other" is not the same as "are".
"[...] guess there is no solution so far" There are two approaches, which might be worth trying

Melden Sie sich an, um zu kommentieren.


Mona Lacatusu
Mona Lacatusu am 3 Sep. 2019
Bearbeitet: per isakson am 4 Feb. 2020
For me it worked to change the marker size from a loaded image in the following way:
image1 = hgload('image_path/file_name.fig');
figure
h(1)=subplot(2,1,1);
copyobj(allchild(get(image1,'CurrentAxes')),h(1));
% Add legends
[~, objh]=legend(h(1),'Data1','Data2','Data3','Location','best')
objhl = findobj(objh, 'type', 'Line'); % objects of legend of type Line
set(objhl, 'Markersize', 40); % set marker size as desired
  1 Kommentar
Carl Witthoft
Carl Witthoft am 4 Feb. 2020
Mona, what version of MATLAB are you using to get that success? Nobody I've found yet can get this to work with any 2019 version

Melden Sie sich an, um zu kommentieren.


Elizabeth Case
Elizabeth Case am 19 Aug. 2021
Bearbeitet: Elizabeth Case am 19 Aug. 2021
I'm using Matlab 2021a. My case use is a bit different than most here but thinking this might prove useful to someone. I am plotting data in a loop, and want the size of the marker in the legend to match the markersize on the scatter plot. I only wanted certain entries to show up in the legend to avoid repetition (in this case, markersize is determined by year).
Note that this does throw warnings, but still seems to work.
Most relevant code for setting legend marker size is marked by %------> <------%
%create data structure -- 3 measurements at 3 locations over multiple years
x = linspace(1,10,12);
y = linspace(0,1,12);
z = linspace(-4,0,12);
names = ['a';'b';'c';'a';'b';'a';'b';'a';'b';'c';'a';'b']; %data
years = [1990,1990,1990,1992,1992,1995,1995,2000,2000,2000,2005,2005]; %data
for i = 1:length(x)
struct(i).x= x(i);
struct(i).y= y(i);
struct(i).z= z(i);
struct(i).name = names(i);
struct(i).year = years(i);
end
%create markersize structure based on year
uyrs = unique([struct.year]); %array of unique years
sz = linspace(10,35,length(uyrs)); %array of sizes, same length as year
for i=1:length(uyrs)
szplot(i).year = uyrs(i);
szplot(i).sz = sz(i);
end
%create color structure based on name
uname = unique({struct.name}); %array of unique names
cols = ['#8c510a';'#fc8d59';'#d8b365'];
for i=1:length(uname)
cplot(i).name = uname{i};
cplot(i).color = cols(i,:);
end
%%
n=1; %keeps track of number of years
figure; tiledlayout(1,2);
for ind=1:length(struct)
nexttile(1)
hold on;
if strcmp(struct(ind).name,'a') %conditional for x data I want to show in legend (1 per year)
cc = cplot(matches({cplot.name},struct(ind).name)).color; %finds correct color based on conditional
size = szplot(n).sz;
year = szplot(n).year;
p1(n) = scatter(struct(ind).x,struct(ind).y,size,'MarkerFaceColor',cc,'DisplayName',num2str(year)); %by giving it a handle (p1) & DisplayName, ensures desired labeled data shows up in legend
n=n+1; %keeps track of number of years
end
cc = cplot(matches({cplot.name},struct(ind).name)).color; %matches color to name
size = szplot([szplot.year]==struct(ind).year).sz; %matches size to year
scatter(struct(ind).x,struct(ind).y,size,'MarkerFaceColor',cc); %plot rest of x data
nexttile(2)
hold on;
scatter(struct(ind).z,struct(ind).y,size,'MarkerFaceColor',cc); %plot z data
drawnow;
%------> <------%
if ind==length(struct)
[lg1,obj]=legend(p1,'Orientation','Horizontal'); %creates obj to find marker size at end of plotting
end
%------> <------%
end
%------> <------%
objhl = findobj(obj, 'type', 'patch'); % finds objects in legend of type patch (e.g. marker)
for i = 1:length(objhl) %iterate through patches to set each size individually
set(objhl(i), 'Markersize', sqrt(szplot(i).sz)); % set marker size according to size structure
end
%------> <------%
lg1.Layout.Tile = 'North';

Produkte


Version

R2017a

Community Treasure Hunt

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

Start Hunting!

Translated by