Search code examples
matlab

Matlab: flip legend order and legend overlapping plots after saving


I'm trying to reverse my legend entries order based on reverse ordering of legend colors in matlab bar plot, but it doesn't seem to work in my case.

Basicaly what I have is a GUIDE figure, that draws a lot of plots and is able to save them to a .png file. The effect looks like this: http://i.imgbox.com/KzEFAdia.png

I've managed to change the text order by flipping legend upside-down, but I can't change legend colors order. Here's what I've got:

[a b] = legend(legenda);

map = colormap; % current colormap

n = size(b,1);

z = linspace(size(map,1),1,n/3); % there is 1 text and 2 line elements for every data series, so I divide by 3

z = round(z); %otherwise matlab gets angry that indices must be real integers or logicals

MAP = map(z(:),:); % gets elements specified by linspace from colormap

So far everything works ok.

The b vector for two series looks like this (starts with 2.0, because it's reversed):

Text    (P+C 200 2.0.dpt)
Text    (P+C 200 1.0.dpt)
Line    (P+C 200 2.0.dpt)
Line    (P+C 200 2.0.dpt)
Line    (P+C 200 1.0.dpt)
Line    (P+C 200 1.0.dpt)

So I figured out (based on the linked code), I have to change the color variable for every line entry.

for k = (n/3 + 1):n
   a1 = get(b(k),'Children');
   set(a1,'FaceColor',MAP(ceil((k - n/3)/2), :));
end

Ceil and dividing by 2 gives the same index twice.

This code, however, does nothing.

I've checked whether flipping the legend vector may be the source of my problems, but the color order stays the same. I've tried with MAP vector too - no luck.

When I remove the semicolon after the a1 = ... line in the for loop, I get:

a1 = 

  0x0 empty GraphicsPlaceholder array.

How can I get this to work?

Also, is there any good way to make the legend not cover the plots after it's saved (see picture linked above)?

The way I save it is by creating a temporary figure with 'visible' 'off' and doing a copyobj of axes and legend, then saving. Otherwise it saves the whole figure.


Solution

  • The reason for which the code provided in the answer to reverse ordering of legend colors in matlab bar plot does not work in your case is because in that case (plot of a bar chart) the object in the legend are patches while in your plot they are lines.

    The FaceColor only applies to patches and not to lines.

    The easiest way to solve you probles should be to reverse the order in which you plot the lines "since the beginning" and, doing that, directly using the set of colors you extract from the colormap.

    Nevertheless, if you wnat to work with the legend after having plotted the graph, beside revrsing the items in the legend you have also to change the color of the lines in the plot, if you want to use the set of color extracted from the colormap (at present in your picture, some lines share the same color).

    To can solve the problem in two steps:

    • revert the string in the legend and change the colors of the line sin the plot
    • update the color of the lines in the legend accordingly

    The two steps are required since, when you change the color of the lines in the plot, the items in the legend are updated automatically.

    With reference to the code youy've posted: you can access to the legend's string and line's color through the array b.

    You can access to the handles of the lines plotted as follows:

    p_h=get(gca,'children')
    

    Since you have plotted 10 lines, the array b is build as follows:

    • b(1:10) contains the handles to the string
    • b(11:2:30) contains the handles to the lines
    • b(12:2:30) contains the handles to the markers

    To chenge the positin of the legend you can set its location property: to put it outside the axes you can set it either to:

        'NorthOutside'       outside plot box near top
        'SouthOutside'       outside bottom
        'EastOutside'        outside right
        'WestOutside'        outside left
        'NorthEastOutside'   outside top right (default for 3-D plots)
        'NorthWestOutside'   outside top left
        'SouthEastOutside'   outside bottom right
        'SouthWestOutside'   outside bottom left
    

    In the following you can find the code in which the above suggestions have been implemented.

    figure
    % Initial plot
    h_p=plot(0:.1:2*pi,bsxfun(@plus,sin([0:.1:2*pi]),[3:3:30]'),'linewidth',3)
    % Initial legend
    [h_leg,b]=legend(cellstr(strcat(repmat('sin(x)+',10,1),num2str([3:3:30]'))))
    %
    % YOUR CODE TO GENERATE NTHE NEW COLORS
    %
    map = colormap; % current colormap
    n = size(b,1);
    z = linspace(size(map,1),1,n/3); % there is 1 text and 2 line elements for every data series, so I divide by 3
    z = round(z); %otherwise matlab gets angry that indices must be real integers or logicals
    MAP = map(z(:),:); % gets elements specified by linspace from colormap
    %
    % Reverse the legend strings
    %
    rev_str=flipud(get(b(1:10),'string'))
    %
    % Get the handles of the lines in the legend
    %
    b1=b(11:2:30)
    %
    % Revere the string in the legend
    % and update the color of the lne in the plot using the colors defined in
    % MAP
    %
    p_h=get(gca,'children')
    for i=1:10
       set(b(i),'string',rev_str{i})
       set(p_h(i),'color',MAP(i,:),'linewidth',3)
    end
    %
    % Reverse the color of the lines in the legend
    for i=1:10
       set(b1(i),'color',MAP(i,:),'linewidth',3)
    end
    %
    % Move the legend outside the axes
    %
    set(h_leg,'location','NorthEastOutside')
    

    Original Plot

    enter image description here

    Updated plot

    enter image description here

    Hope this helps.