Add custom legend without any relation to the graph - matlab

I wish to insert a legend that is not related to the graph whatsoever:
figure;
hold on;
plot(0,0,'or');
plot(0,0,'ob');
plot(0,0,'ok');
leg = legend('red','blue','black');
Now I wish to add it to another figure:
figure;
t=linspace(0,10,100);
plot(t,sin(t));
%% ADD THE LEGEND OF PLOT ABOVE

This is how I have solved this problem in the past:
figure
t=linspace(0,10,100);
plot(t,sin(t));
hold on;
h = zeros(3, 1);
h(1) = plot(NaN,NaN,'or');
h(2) = plot(NaN,NaN,'ob');
h(3) = plot(NaN,NaN,'ok');
legend(h, 'red','blue','black');
This will plot the additional points, but because the coordinates are at NaN they will not be visible on the plot itself:
EDIT 26/10/2016: My original answer results in greyed out legend entries in 2016b. The updated code above works, but the answer below is only relevant pre-2016b:
figure
t=linspace(0,10,100);
plot(t,sin(t));
hold on;
h = zeros(3, 1);
h(1) = plot(0,0,'or', 'visible', 'off');
h(2) = plot(0,0,'ob', 'visible', 'off');
h(3) = plot(0,0,'ok', 'visible', 'off');
legend(h, 'red','blue','black');
This will plot the additional points, but they will not be visible on the plot itself.
You can also use copyobj to copy graphics elements from one figure to another if you have a lot of elements, then use set(x, 'visible', 'off') to hide them before showing the legend, but it depends on what your final application is.

Your question is a little unclear. However, the first thing I thought of when reading it was the text function in Matlab.
You can use the text function to add text to a Matlab figure. It's use is
>> text(x, y, str);
where x and y are the coordinates in the figure where you want to add the text str. You can use the Color option of text for colours and TeX to draw lines or even _. I've gotten very creative with plots using text.
Here's a quick and dirty example of emulating a legend with text
x = 0:pi/20:2*pi;
y = sin(x);
plot(x,y)
axis tight
legend('sin(x)');
text(5.7, 0.75, 'sin(x)');
text(5.1, 0.78, '_____', 'Color', 'blue');
which produces
For this specific case you could use the specific command (noted by #Hoki in the comments).
ht = text(5, 0.5, {'{\color{red} o } Red', '{\color{blue} o } Blue', '{\color{black} o } Black'}, 'EdgeColor', 'k');
to produce
by retrieving the handle to the text object it becomes trivial to copy it to a new figure, copyobj(ht, newfig). [1]

Related

matlab : suppress legend entry without removing from Plot Browser

One can suppress a legend entry for a line object h by executing h.HandleVisibility='off' or h.Annotation.LegendInformation.IconDisplayStyle='off'. However, both actions also prevent the curve from appearing in Matlab's Plot Browser user interface, and thus display of the curve cannot be interactively toggled.
Is there any way to suppress a legend entry for a given curve without also removing the ability to toggle display of that curve in the Plot Browser user interface?
You can also turn off handle visibility. This is way easier than having to set every plot as h1 = ...
Example:
x1 = randperm(10);
y = randperm(10);
x2 = randperm(10);
plot(x1, y, '-', 'Color', 'black', 'HandleVisibility', 'off')
hold on
plot(x2, y, '-', 'Color', 'green', 'DisplayName', 'Put This In Legend')
lgd = legend;
set(lgd, 'Location', 'best')
MATLAB's legend function accepts an optional argument listing the handles to include in the legend:
figure, hold on
h1 = plot(1,1,'ro');
h2 = plot(1,2,'gx');
h3 = plot(2,1,'m*');
legend([h1,h3]); % don't make a legend for h2.

Matlab - plot - How to get the x-axis labels in a color keeping the x-axis color black and the first tick value hidden?

How to get the xaxis labels 2 4 6 in blue keeping the x-axis color black and the first tick value hidden?
when I am trying to change the tick label color the tick labels disappear
x=0:0.25:5
y=sin(x)
ax1 = subplot(1,2,1) ;
plot(x,y)
set(gca, 'YAxisLocation', 'right')
xlabel('x','Color','b')
ylabel('y')
%set(gca,'xColor','k');
%set(gca,'xticklabel','b')
Q=get(gca,'xtick');
R=get(gca,'xticklabel');
set(gca,'xtick',Q(2:end))
set(gca,'xticklabel',R(2:end,:))
You can do this using the undocumented XRuler property of the axis:
h = gca;
h.XRuler.TickLabels.ColorData = uint8([0;0;255;255]);
Note this might not be available in older versions of MATLAB, it works for me on 2015a
Inspired by this answer, I decided to try and solve your problem in a similar manner. I was able to find a working solution, but it's not pretty as you need to copy several axes objects, and it seems that it's not robust to resizing of the figure. Hopefully it will still be helpful!
The code is below.
%//Original code
x=0:0.25:5;
y=sin(x);
ax1 = subplot(1,2,1);
plot(x,y)
set(ax1, 'YAxisLocation', 'right')
ylabel(ax1, 'y');
xlabel(ax1, 'x', 'Color', 'b'); %// Give the blue 'x' as label
%//Solution
my_xticks = [2 4 6]; %// The XTicks you want to show
drawnow; %//Must draw the axes here due to YAxisLocation, otherwise will not work
ax2 = copyobj(ax1, gcf); %// Create a copy the axes
set(ax2, 'XTick', my_xticks, 'XColor', 'b', 'Color', 'none') %// Keep only my_xticks in blue
ax3 = copyobj(ax1, gcf); %// Create another copy...
set(ax3, 'XTick', [], 'Color', 'none'); %// From which we keep only the black gridline
xlabel(ax3, ''); %// Remove the xlabel from ax3 (would show x in wrong position)
set(ax1, 'xtick', my_xticks); %// In ax1, show black ticks at desired locations
End result looks like this:
Caveats, as mentioned: You are copying the axes object twice, which is wasteful. If you resize the figure, the construction seems to implode. I could not figure out how to fix these.

Why is the actual value of an axis position different than the derived value in MATLAB suplot figure?

I've got a figure with two subplots being displayed. I want to get the axis position of each plot so I am using the figure's children information:
subplot(211)
% Plot stuff here
...
subplot(212)
% Plot stuff here
...
% Get Axes Position information
f =gcf;
% Bottom Plot Axis
disp(f.Children(2).Position)
% Top Plot Axis
disp(f.Children(4).Position)
The console displays:
Bottom plot:
0.1300 0.1100 0.7750 0.3412
Top plot:
0.1300 0.5838 0.7750 0.3412
This seems correct given all else. When I run the plot to generate the figure and then inspect the axes' information via 'Show Plot Tools and Dock Figure->Inspector: matlab.graphics.axis.Axes' option the width value for each axis's position is not 0.7750. The other position values are as listed but the width is different for both the top and bottom plots. The top becomes [0.13 0.5838 0.682 0.341] and the bottom becomes [0.13 0.11 0.67 0.341].
Does anyone know why this is and how to get the "real" position values and not the incorrect displayed/printed ones?
Useful info: MATLAB R2014b
EDIT UPDATE:
Here is a MWE that produces the behavior.
clear all; close all; clc;
figure;
subplot(211)
hold on
x1 = [ -1 -0.998 -0.996 -0.994 -0.992];
y = [0.000324249267578125 -0.000370025634765625 -3.4332275390625e-005 -0.000186920166015625 -0.000110626220703125];
plot(x1, y, '-', 'MarkerSize', 10)
set(gca, 'FontName', 'Interstate-Light', 'FontSize', 7)
set(gca, 'XTickLabel', [])
set(gca, 'XLabel', [])
grid on
ylabel('Frequency Error (Hz)', 'FontName', 'Interstate-Bold')
legend({'FE'}, 'Location', 'NorthEastOutside', 'FontName', 'Interstate-Light', 'Box', 'off')
subplot(212)
hold on
x1 = [ -1 -0.998 -0.996 -0.994 -0.992];
y = [-0.010614013299346 -0.0417663566768169 0.0235949698835611 -0.0502893067896366 0.0316442884504795];
plot(x1, y, '-', 'MarkerSize', 10)
% Overide X-axis ticks to align with data
XTick = unique(x1);
grid on;
xlabel('Time (s)', 'FontName', 'Interstate-Bold')
ylabel('Frequency Error (Hz)', 'FontName', 'Interstate-Bold')
set(gca, 'FontName', 'Interstate-Light', 'FontSize', 7)
legend({'RFE'}, 'Location', 'NorthEastOutside', 'FontName', 'Interstate-Light', 'Box', 'off')
% Get figure object
f = gcf;
% Set fontsize to 16 for readability in final pdf
set(findall(f, '-property','FontSize'),'FontSize',16)
f.PaperUnits = 'inches';
f.PaperPosition = [0 0 20 14];
f.PaperPositionMode = 'manual';
% Get axis position info
disp('Second plot:')
disp(f.Children(2).Position)
disp('First Plot:')
disp(f.Children(4).Position)
I'm working with R2012b and I've been able to reproduce the problem and also (almost) been able to understand what's happening.
I do not know if it is also applicable to more "recent" versin of MatLab.
The problem seems related to the default configuration of the window Show Plot Tools and Dock Figure
With this configuration, actually the position of the two axes (read in the Property editor are different with respect to the "original ones:
original pos ax 1= [0.1300 0.5838 0.7750 0.3412]
new pos ax1=[0.1300 0.629 0.7750 0.268 ]
Nevertheless, if you minimize the Property editor tab and look at the Position of the two axes, they are restored to the "original" one values.
You can, the "slide up" the tab and the position still remain the "original onne.
I'do not know if this is actually an answer to you question; what I can say is that the right position position are the "original" ones.
It could be a sort of bug in the visualization in the default configuratin od the Show Plot Tools and Dock Figure window.
Hope this helps.

How can I show only the legend in MATLAB

I want to show only the legend for a group of data in MATLAB.
The reason I want to do this is that I want to export the legend to .eps, but I only want the legend, not the plots.
Is there a way to turn off the plots and remove them from the figure, but still show just the legend centered?
This seems to do the trick:
plot(0,0,'k',0,0,'.r') %make dummy plot with the right linestyle
axis([10,11,10,11]) %move dummy points out of view
legend('black line','red dot')
axis off %hide axis
There is probably a lot of whitespace around the legend. You could try to resize the legend by hand, or save the plot and use some other program to set the bounding box of the eps.
The chosen solution by Marcin doesn't work anymore for R2016b because MATLAB's legend will automatically gray out invisible plots like this:
Neither turning off the automatic update of the legend nor changing the TextColor property afterwards fixes this. To see that, try Marcin's modified example:
clear all; close all;
figHandle = figure;
p1 = plot([1:10], [1:10], '+-');
hold on;
p2 = plot([1:10], [1:10]+2, 'o--');
legHandle = legend('text1', 'text2');
%turn off auto update
set(figHandle,'defaultLegendAutoUpdate','off');
set(p1, 'visible', 'off');
set(p2, 'visible', 'off');
set(gca, 'visible', 'off');
%set legend text color to black
legHandle.TextColor = [0 0 0];
The result remains the same. (To avoid throwing my laptop through the window) and fix this without zooming, which might leave fragments of the plot in the way, I wrote a function that fixes the legend and saves it to a file (with frame):
function saveLegendToImage(figHandle, legHandle, ...
fileName, fileType)
%make all contents in figure invisible
allLineHandles = findall(figHandle, 'type', 'line');
for i = 1:length(allLineHandles)
allLineHandles(i).XData = NaN; %ignore warnings
end
%make axes invisible
axis off
%move legend to lower left corner of figure window
legHandle.Units = 'pixels';
boxLineWidth = legHandle.LineWidth;
%save isn't accurate and would swallow part of the box without factors
legHandle.Position = [6 * boxLineWidth, 6 * boxLineWidth, ...
legHandle.Position(3), legHandle.Position(4)];
legLocPixels = legHandle.Position;
%make figure window fit legend
figHandle.Units = 'pixels';
figHandle.InnerPosition = [1, 1, legLocPixels(3) + 12 * boxLineWidth, ...
legLocPixels(4) + 12 * boxLineWidth];
%save legend
saveas(figHandle, [fileName, '.', fileType], fileType);
end
Tips for use:
fileType is a string that specifies a valid argument for saveas(), such as 'tif'.
Use it after you have plotted everything you want to appear in your legend, but without extra stuff. I'm not sure if all potential elements of a plot contain an XData member that isn't empty.
Add other types of displayed things that you want deleted, but are not of type line if there are any.
The resulting image will contain the legend, its box, and a little bit of space around it the legend is smaller than the minimum width (see Minimum Width of Figures in MATLAB under Windows). However, this is usually not the case.
Here is a complete example using the function from above:
clear all; close all;
fig = figure;
p1 = plot([1:10], [1:10], '+-');
hold on;
p2 = plot([1:10], [1:10]+2, 'o--');
legendHandle = legend('myPrettyGraph', 'evenMoreGraphs');
saveLegendToImage(fig, legendHandle, 'testImage', 'tif');
I think that you need to "hide" the elements you don't want in your plot, leaving out only the legend. For example,
clear all; close all;
figure;
p1 = plot([1:10], [1:10], '+-');
hold on;
p2 = plot([1:10], [1:10]+2, 'o--');
legend('text1', 'text2');
set(p1, 'visible', 'off');
set(p2, 'visible', 'off');
set(gca, 'visible', 'off');

In MATLAB, how does one clear the last thing plotted to a figure?

In MATLAB, I plot many different vectors to a figure. Now, what I would like to do is simply undo the last vector that I plotted to that figure, without clearing everything else. How can this be accomplished? Can it be accomplished?
Thanks
Edit:
figure(1); clf(1);
N = 100;
x = randn(1,N);
y = randn(1,N);
z = sin(1:N);
plot(x); hold on;
plot(y,'r');
plot(z,'k');
Now here, I would like to remove the plot z, which was the last plot I made.
If you know before plotting that you want to remove it again later, you can save the handle returned by plot and delete it afterwards.
figure;
h1 = plot([0 1 2], [3 4 5]);
delete(h1);
Try
items = get(gca, 'Children');
delete(items(end));
(or maybe delete(items(1)))
The answer that #groovingandi gives is the best way to generally do it. You can also use FINDALL to find the handle based on the properties of the object:
h = findall(gca, 'type', 'line', 'color', 'k');
delete(h);
This searches the current axes for all line objects (plot produces line objects) that are colored black.
To do this on, say, figure 9, you need to find the axes for figure 9. Figure handles are simply the figure number, so:
ax = findall(9, 'axes');
h = findall(ax, 'type', 'line', 'color', 'k');
delete(h);