Matlab: how do I retrieve the title, the xlabel, the ylabel and font of a plotyy? - matlab

I have some figures, for which I want to change:
The title
The xlabel and the ylabel (both font size and content)
The ticks size.
This is how I usually do it:
title('new title ');
xlhand = get(gca,'xlabel');
set(xlhand,'string','xlabel','fontsize',13);
ylhand = get(gca,'ylabel');
set(ylhand,'string','ylabel','fontsize',13);
set(gca,'FontSize',13);
It usually works fine. However, it doesn't work when I want to edit a plot made with the ploty function. The only effect is that my right ylabel changes.
I'm aware that since I have two ylabels now, changing them won't be as easy as for a normal plot. However, I'm surprised that I can't change the xlabels and the title. Why is that?
What's wrong with the above code in relation to the plotxy function? How can I make it work? The documentation doesn't contain any relevant information.
I'm using Matlab R2015a.
Edit: Yes, I meant plotyy (there was a typo in my question). Here is sample code from the documentation:
x = 0:0.01:20;
y1 = 200*exp(-0.05*x).*sin(x);
y2 = 0.8*exp(-0.5*x).*sin(10*x);
figure % new figure
plotyy(x,y1,x,y2)

If you look at the documentation, you can see that plotyy can return the axis handles. So first, you that option to obtain the handles:
Ax = plotyy(x,y1,x,y2);
Now, Ax(1) is the handle to the left axes and Ax(2) is the right one. So you can change the attributes of each of them, for example
set(Ax(1),'FontSize',13);
For reasons I don't fully understand, setting the label is done using
set(get(Ax(1),'YLabel'),'String','Whatever you want...');
EDIT:
If you already plotted the data, you can retrieve the handles using
Ax = findobj(gcf,'type','axes')

From documentation without using get, set :
x = 0:0.01:20;
y1 = 200*exp(-0.05*x).*sin(x);
y2 = 0.8*exp(-0.5*x).*sin(10*x);
figure % new figure
hAx = plotyy(x,y1,x,y2);
title('Multiple Decay Rates')
xlabel('Time (\musec)')
ylabel(hAx(1),'Slow Decay') % left y-axis
ylabel(hAx(2),'Fast Decay') % right y-axis
Then change values by
xlabel('New label','fontsize',10)
title('New Title','fontsize',10)
ylabel(hAx(2),'Fast Decay','fontsize',20)
hAx(1).FontSize=5

Related

Labeling plots such that label is aligned with the ylabel outside the axes

Please see the following code which creates a 2 by 2 subplot with some plots:
x = linspace(0,2*pi);
y = sin(x);
hfig = figure('Position',[1317 474 760 729]);
subplot(2,2,1)
plot(x,y)
ylabel('plot1');
subplot(2,2,2)
plot(x,y.^2)
ylabel('plot2');
subplot(2,2,3)
plot(x,y.^3)
ylabel('plot3');
subplot(2,2,4)
plot(x,abs(y))
ylabel('plot4');
in each one, I have added labels by hand in Tools: Edit plot (a) (b) (c) (d) producing this figure:
The problem is, if I resize the plot they are no longer aligned with the ylabel text:
Is there a way to add these labels programmatically and have them automatically align to the ylabel text? I am surprised MATLAB does not have something like this built in already.
Thanks
This is not something that is easy to do without attaching a listener to the figure resize event (see example), and doing some computations related to aspect ratios.
It's not entirely clear what sort of objects your labels are (text or annotation), so I'll just show how to do this programmatically using the text command, which creates labels in axes coordinates (as opposed to figure coordinates). This doesn't solve the problem entirely, but it looks better, possibly to an acceptable degree:
function q56624258
x = linspace(0,2*pi);
y = sin(x);
hF = figure('Position',[-1500 174 760 729]);
%% Create plots
[hAx,hYL] = deal(gobjects(4,1));
for ind1 = 1:3
hAx(ind1) = subplot(2,2,ind1, 'Parent' , hF);
plot(hAx(ind1), x,y.^ind1);
hYL(ind1) = ylabel("plot" + ind1);
end
hAx(4) = subplot(2,2,4);
plot(hAx(4), x,abs(y));
hYL(4) = ylabel('plot4');
%% Add texts (in data coordinates; x-position is copied from the y-label)
for ind1 = 1:4
text(hAx(ind1), hYL(ind1).Position(1), 1.1, ['(' char('a'+ind1-1) ')'], ...
'HorizontalAlignment', 'center');
end
Note several modifications to your code:
The handles returned by some functions that create graphical elements are now stored (mainly: hAx, hYL).
All functions that create graphical elements (subplot, plot, ylabel) now have the target (i.e. parent or container) specified.
I changed the 'Position' of the figure so that it works in my setup (you might want to change it back).

Include axes labels when saving plot from MATLAB GUI

I have written the following code to try and retrieve ONLY the axes and its plot from my MATLAB GUI.
F = getframe(gca);
figure();
image(F.cdata);
saveas(gcf,'PlotPic','png');
close(gcf);
I noticed, however, that this method does not include ANY of my axis labels or title. Is there any way which I can get the getframe function to include the axis labels and title?
I tried the following code but it did exactly the same
pl = plot(x,y);
xlabel('x')
ylabel('y')
ftmp = figure;
atmp = axes;
copyobj(pl,atmp);
saveas(ftmp,'PlotPic.png');
delete(ftmp);
I would do it using the rect option of the getframe function.
Basically you can provide a 2nd input argument to getframe, which then captures the content of the rectangle specified as argument. The nice thing is that you can use the handles to an axes, so it does not capture your whole GUI figure but rather a specific axes.
For example, using this line:
F = getframe(gca,RectanglePosition);
Concretely, you could set the coordinates of the rectangle such that they span both axis labels and the title as well. Here is a sample code. The pushbutton callback executes getframe and opens a new figure with the content of F.cdata:
function GUI_GetFrame
clc
clear
close all
%// Create GUI components
hFigure = figure('Position',[100 100 500 500],'Units','Pixels');
handles.axes1 = axes('Units','Pixels','Position',[60,90,400,300]);
handles.Button = uicontrol('Style','Push','Position',[200 470 60 20],'String','Get frame','Callback',#(s,e) GetFrameCallback);
%// Just create a dummy plot to illustrate
handles.Period = 2*pi;
handles.Frequency = 1/handles.Period;
handles.x = 0:pi/10:2*pi;
handles.y = rand(1)*sin(handles.Period.*handles.x);
plot(handles.x,handles.y,'Parent',handles.axes1)
title('This is a nice title','FontSize',18);
guidata(hFigure,handles); %// Save handles structure of GUI.
function GetFrameCallback(~,~)
handles = guidata(hFigure);
%// Get the position of the axes you are interested in. The 3rd and
%// 4th coordinates are useful (width and height).
AxesPos = get(handles.axes1,'Position');
%// Call getframe with a custom rectangle size.You might need to change this.
F = getframe(gca,[-30 -30 AxesPos(3)+50 AxesPos(4)+80]);
%// Just to display the result
figure()
imshow(F.cdata)
end
end
The GUI looks like this:
And once I press the pushbutton, this is the figure that pops up:
So the only trouble you have is to figure out the dimensions of the rectangle you need to select to capture the axis labels and the title.
Hope that solves your problem!

How to augment two Matlab plots?

I would like to plot two graphs with the same x-axis but with different y-axies, one stacked above the other. There is a similar question asked below BUT it doesn't account for changes of dimensions in the y-axes. I have edited this code to do so but hope there would be a more elegant approach (maybe using a "hold on" type code).
How to plot graphs above each other in Matlab?
Here is some code which might do what you want...if I understood right. Basically you create 2 different axes in the same figure, one on top of the other, and you play around with XTick and YTick. You can start from this I guess.:
clear
close all
clc
x = 1:10;
y1 = -(x.^2);
y2 = sin(x);
figure('Units','Normalized');
hAxes1 = axes('Position',[0.1 0.1 .8 .4]);
yLim = get(hAxes1,'YLim');
Axes1Position = get(hAxes1,'Position');
NewAxesPosition = [Axes1Position(1) Axes1Position(2)+0.4 Axes1Position(3) Axes1Position(4)];
hAxes2 = axes('Position',NewAxesPosition);
plot(x,y1,'b','Parent',hAxes1);
TICK = get(hAxes1,'YTick')
set(hAxes1,'XTick',2:1:10,'YTick',TICK(1:end-1))
hold on
plot(x,y2,'r','parent',hAxes2)
set(gca,'XTick',[],'XTickLabel',[])
hold off
Giving this:
This is not optimal but due to lack of time I have to stop here :) Of course you can alter the display of the axis or the tick marks as you wish. Moreover you could use text annotations to customize the YTicks even more nicely.Hope that helps!
Example:
A = 1000;
a = 0.005;
b = 0.005;
t = 0:900;
z1 = A*exp(-a*t);
z2 = sin(b*t);
[ax,p1,p2] = plotyy(t,z1,t,z2,'semilogy','plot');
ylabel(ax(1),'Semilog Plot') % label left y-axis
ylabel(ax(2),'Linear Plot') % label right y-axis
xlabel(ax(2),'Time') % label x-axis
With reference to: http://www.mathworks.com/help/matlab/creating_plots/plotting-with-two-y-axes.html

Overlaying two axes in a Matlab plot

I am looking for a way to overlay an x-y time series, say created with 'plot', on top of a display generated by 'contourf', with different scaling on the y-axes.
It seems that the typical way to do this in the case of two x-y plots is to use the built-in function 'plotyy', which can even be driven by functions other than 'plot' (such as 'loglog') as long as the input arguments remain the same (x,y). However, since in my case contourf requires three input arguments, 'plotyy' seems to not be applicable. Here is some sample code describing what I would like to do:
x1 = 1:1:50;
y1 = 1:1:10;
temp_data = rand(10,50);
y2 = rand(50,1)*20;
figure; hold on;
contourf(x1,y1,temp_data);
colormap('gray');
plot(x1,y2,'r-');
Ideally, I would like the timeseries (x1,y2) to have its own y-axes displayed on the right, and be scaled to the same vertical extent as the contourf plot.
Thanks for your time.
I don't think there's a "clean" way to do this, but you can fake it by overlaying two axes over each other.
x1 = 1:1:50;
y1 = 1:1:10;
temp_data = rand(10,50);
y2 = rand(50,1)*20;
figure;
contourf(x1, y1, temp_data);
colormap('gray');
h_ax = gca;
h_ax_line = axes('position', get(h_ax, 'position')); % Create a new axes in the same position as the first one, overlaid on top
plot(x1,y2,'r-');
set(h_ax_line, 'YAxisLocation', 'right', 'xlim', get(h_ax, 'xlim'), 'color', 'none'); % Put the new axes' y labels on the right, set the x limits the same as the original axes', and make the background transparent
ylabel(h_ax, 'Contour y-values');
ylabel(h_ax_line, 'Line y-values');
In fact, this "plot overlay" is almost definitely what the plotyy function does internally.
Here's example output (I increased the font size for legibility):

Trying to make MATLAB's figure stop 'blinking'

So I have a simple loop in MATLAB that does the following:
for p = 1:100
x = 4.*randn(1,100);
y = 7.*randn(1,100);
figure(1)
plot(randn(1,100));
figure(2);
plot(randn(1,100));
end
The x and y are made up, but that is the jist of it. Anyway, when I run this code, not surprisingly, MATLAB will make two figures and plot accordingly. The problem is, I get a sort of 'blinking' between figures when I do this, and it makes the quality of seeing x and y evolve over time poorer.
I discovered a way to make one of the plots smoother like this:
figure(1);
for p = 1:100
x = 4.*randn(1,100);
y = 7.*randn(1,100);
plot(randn(1,100));
drawnow
end
If I do this, then of course figure(1) will plot very smoothly showing x nicely, without figure(1) 'blinking' between plots, but now I cant show figure(2) or y!
How can I plot both those quantities on different figures (not subplots) smoothly without 'blinking'?
EDIT:
Thanks Geodesic for your answer, the solution works, however there is a subtlety that I did not think would be an issue, however it is.
1) I am unable to use 'imagesc' with this solution.
For example,
figure(1);
aone = axes;
figure(2);
atwo = axes;
for p = 1:100
x = 4.*randn(1,100);
y = 7.*rand(10,100);
plot(aone,x);
drawnow;
imagesc(atwo,y);
drawnow;
end
In this case the part with imagesc(atwo, y) crashes.
Your flicker is because you're generating each figure window again and again through the loop, which is forcing the window to come to the foreground each time. Generate the figures first, attach some axes to them, and plot your data to each axis like so:
figure(1);
aone = axes;
figure(2);
atwo = axes;
for p = 1:100
x = 4.*randn(1,100);
y = 7.*randn(1,100);
plot(aone,randn(1,100));
drawnow;
imagesc(y,'Parent',atwo);
drawnow;
end
Edit: functions like plot take an axis argument directly, but imagesc does not. In this particular case you'll need to send a Property Name/Value pair in as an argument. The 'Parent' of the image generated will be our axis atwo (see above).
For p = 1, create the plots you need, using the plot command or the imagesc command. Keep the handle of the resulting graphics object by getting an output argument: for example h = plot(.... or h = imagesc(..... This will be a Handle Graphics lineseries or image object, or something else, depending on the particular plot type you create.
For p = 2:100, don't use the plotting commands directly, but instead update the relevant Data properties of the original Handle Graphics object h. For example, for a lineseries object resulting from a plot command, set its XData and YData properties to the new data. For an image object resulting from an imagesc command, set its CData property to the new image.
If necessary, call drawnow after updating to force a flush of the graphics queue.