Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to put the text labels (keys) to the left of the lines in the legend?

I searched in many places and didn't find a way to do what I would like to achieve using MATLAB which is this: putting the keys (text labels) to the left of the color lines in the legend in MATLAB.

enter image description here

I would like to achieve this result that is the default result using gnuplot for instance (cf link above) and that is apparently doable using MATLAB's cousin Octave (see Octave's legend) that has an option to do legend("left") that "place[s] label text to the left of the keys."

Is it possible to do so using MATLAB?

like image 267
viiv Avatar asked May 17 '16 21:05

viiv


3 Answers

Updated slightly using the second output of legend mentioned by @nirvana-msu.

We can adjust the positions of the text and plot object in the legend by retrieving their current position and altering it. The position units of all items in the legend are normalized data units between 0 and 1.

Something like the following should work.

%// Create some random data and display
figure;
p = plot(rand(2,3));
[L, handles] = legend({'one', 'two', 'three'});

%// Get the text handles
texts = findall(handles, 'type', 'text');

%// Get the line handles
lines = findall(handles, 'type', 'line');

%// Get the XData of all the lines
poslines = get(lines, 'XData');

%// Subtract 1 from all the positions and take the absolute value
%// this will shift them to the other side as the xlims are [0 1]
set(lines, {'XData'}, cellfun(@(x)abs(x - 1), poslines, 'uni', 0))

%// Get the position of all of the text labels
postext = get(texts, 'Position');

%// Figure out where the lines ended up
xd = get(lines, 'xdata');
xd = cat(2, xd{:});

%// Have the labels be next to the line (with 0.05 padding)
positions = cellfun(@(x)[min(xd) - 0.05, x(2:3)], postext, 'uni', 0);
set(texts, {'Position'}, positions, ...
           'HorizontalAlignment', 'right');

R2014a

enter image description here

R2015b

enter image description here

like image 105
Suever Avatar answered Oct 19 '22 23:10

Suever


Here's a solution that works on HG1 and HG2 alike.

The idea is somewhat similar to that in @Suever's answer - we want to flip around all text, lines and markers inside the legend, however there are some notable differences:

  1. There's no need to search for line and text handles using findall - they are available as the second output of legend function.
  2. There's no need to guess what the reasonable position should be. We just need to flip all controls symmetrically. With lines it's easy as you have XData with both start and end points. With text it's a bit more tricky since you need to control Position, i.e. left edge, but you need to know text width to calculate symmetrical transformation. Extent property gives us what we're missing.

Code:

hFig = figure();
axh = axes('Parent', hFig);
plot(axh, randn(100,2), '-*');
[~, hObjs] = legend(axh, {'first','second-some-long-text'});

for i = 1:length(hObjs)
    hdl = hObjs(i);
    if strcmp(get(hdl, 'Type'), 'text')
        pos = get(hdl, 'Position');
        extent = get(hdl, 'Extent');    % we need text x-position and width
        pos(1) = 1-extent(1)-extent(3); % symmetrical relative to center
        set(hdl, 'Position', pos);
    else     % 'line'
        xData = get(hdl, 'XData');
        if length(xData) == 2 % line
            xDataNew = [1-xData(2), 1-xData(1)];
        else % length(xData)==1, i.e. marker
            xDataNew = 1-xData;
        end
        set(hdl, 'XData', xDataNew);
    end
end

enter image description here

like image 29
nirvana-msu Avatar answered Oct 20 '22 01:10

nirvana-msu


I've decided to take a slightly different approach for the HG2 case. Although admittedly somewhat silly, it could actually be useful if the figure ends up being exported.

What we do is pretty much rotate every conceivable thing by 180°:

function q37286345
%// Define some functions:
f = {'sin(x)','cos(x)','-2E-3.*x.^3'};
figure(); hold on;
for ind1 = 1:numel(f)
  ezplot(f{ind1}, [-10 10]); 
end
title(''); %// Just because I find the default annoying :)
%// Rotate stuff:
[L,H] = legend(f{:},'Location','SouthWest');
[H(1:3).Rotation] = deal(180);
[H(1:3).HorizontalAlignment] = deal('right');
set(gca,'XTickLabelRotation',180,'YTickLabelRotation',180,...
        'XAxisLocation','top','YAxisLocation','right');

The result looks approximately like this:

The rotated image

There are several easily-remedied side effects:

  • The legend entry order will be an opposite of the plotting order (unless the Children of Legend are reordered.
  • The axes' labels will also require rotation (or elimination...).

Side note:

We can explore the Legend metaclass ('matlab.graphics.illustration.Legend') to learn more about HG2:

%% // Exploring.....
mc = metaclass(L);
pl = {mc.PropertyList.Name}.'; %'
ml = {mc.MethodList.Name}.'; %'
s = struct(L);
like image 23
Dev-iL Avatar answered Oct 20 '22 00:10

Dev-iL