I am coding some GUI staff using Matlab. And I want to plot a figure with subfigures in one specified 'axes' using 'subaxis' method (which can be download on Matlab FX subaxis.m).
The program behaves quite right at first. As the subfigures are updating by one click button. Then the error pops-up. I simplify the problem and write some testing codes as following:
% Specify an 'axes' in my GUI (here is an example of axes handle called 'ax')
ax = axes;
axes(ax);
cla(ax, 'reset');
% Plot something using 'subaxis' with multiple subfigures
x = 0:0.1:10;
spacing = 0.0;
subaxis(3,1,1,'Spacing',spacing);
plot(x,rand(size(x)),'k')
legend('D','Location','NorthWest')
ylim([-0.2 1])
set(gca, 'box','off')
set(gca,'XAxisLocation','top')
subaxis(2,'Spacing',spacing);
plot(x,rand(size(x)),'r')
legend('C','Location','NorthWest')
ylim([-0.2 1])
set(gca,'xtick',[],'box','off','xcolor','w')
subaxis(3,'Spacing',spacing);
plot(x,rand(size(x)),'b')
legend('B','Location','NorthWest')
set(gca, 'box','off')
The program is fine at this point and did what I expected. Now I press a button to update these subfigures, but still want to plot the subfigures in the specified axes called 'ax':
axes(ax);
cla(ax, 'reset');
x = 0:0.1:10;
spacing = 0.0;
subaxis(3,1,1,'Spacing',spacing);
plot(x,rand(size(x)),'k')
legend('D','Location','NorthWest')
ylim([-0.2 1])
set(gca, 'box','off')
set(gca,'XAxisLocation','top')
subaxis(2,'Spacing',spacing);
plot(x,rand(size(x)),'r')
legend('C','Location','NorthWest')
ylim([-0.2 1])
set(gca,'xtick',[],'box','off','xcolor','w')
subaxis(3,'Spacing',spacing);
plot(x,rand(size(x)),'b')
legend('B','Location','NorthWest')
set(gca, 'box','off')
Error shows up!!!
Error using axes
Invalid object handle
Not sure what to do as the error info is so brief. It seems the subaxis can only be plot to a specific 'axes' once.
Any help would be appreciated. Thanks very much. A.
Remove these two lines from the top of your second piece of code:
axes(ax);
cla(ax, 'reset');
Now matlab will update the graph in the current plot. I have tested this in a normal (non-GUI) matlab file and it works fine. If it doesn't work for you, post details of the GUI as there may be some related problem within.
Related
I tried creating a plot with two YAxis like this:
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
[hAx,hLine1,hLine2]=plotyy([x',x'],[y1',y2'],x,y3);
Now i have two problem with this code:
I can change the Linestyles of the two hLines using hLine1.LineStyle = ':'; for example, but i can not change the styles of the two lines, that hLine1 consists of. Does anyone know how to do this?
I can't use hLine2.YLim = [0 100] to manually adjust the y-limits shown on the 2nd y-axis.
After I couldn't solve the problem using the plotyy, I searched the MATLAB documentation and found another way of implementing my plot, which I thought might be easier to handle:
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
figure
hold on;
line(x,y1,'Color','r')
line(x,y2,'Color','y')
ax1 = gca;
ax2 = axes('Position',ax1.Position,'YAxisLocation','right');
line(x,y3,'Parent',ax2,'Color','b')
The problem here is, that it doesn't even show the first and the second line, but only the third and i don't know why. I would prefer getting the problem solved using the plotyy, but if that's not possible I would appreciate a solution for the 2nd piece of code as well.
I think you haven't noticed that the outputs of plotyy are arrays of objects, and not single objects.
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
[hAx,hLine1,hLine2]=plotyy([x',x'],[y1',y2'],x,y3);
hLine1(1).LineStyle = '--';
hLine1(2).LineStyle = ':';
% either this
ylim( hAx(2), [0 110] );
% or alternatively
f=gcf; ylim( f.Children(2), [0 110] );
You're not seeing the first two lines because axes backgrounds are white by default. Setting the Color property of the second axes object to 'none' should give you what you're looking for:
x=linspace(0,20);
y1=linspace(10,10);
y2=x.^2;
y3=y2-y1;
figure
hold on;
line(x,y1,'Color','r')
line(x,y2,'Color','y')
ax1 = gca;
ax2 = axes('Position',ax1.Position,'YAxisLocation','right', 'Color', 'none');
line(x,y3,'Parent',ax2,'Color','b')
EDIT: I'd also recommend checking out linkaxes if you're going to be zooming/panning your axes and want to keep some or all of the axes synchronized.
Suppose that I have 2 figures in MATLAB both of which plot data of size (512x512), however one figure is being plotted by an external program which is sets the axis parameters. The other is being plotted by me (using imagesc). Currently the figures, or rather, the axes are different sizes and my question is, how do I make them equal?.
The reason for my question, is that I would like to export them to pdf format for inclusion in a latex document, and I would like to have them be the same size without further processing.
Thanks in Advance, N
Edit: link to figures
figure 1: (big)
link to smaller figure (i.e. the one whose properties I would like to copy and apply to figure 1)
For this purpose use linkaxes():
% Load some data included with MATLAB
load clown
% Plot a histogram in the first subplot
figure
ax(1) = subplot(211);
hist(X(:),100)
% Create second subplot
ax(2) = subplot(212);
Now link the axes of the two subplots:
linkaxes(ax)
By plotting on the second subplot, the first one will adapt
imagesc(X)
First, you have the following:
Then:
Extending the example to images only:
load clown
figure
imagesc(X)
h(1) = gca;
I = imread('eight.tif');
figure
imagesc(I)
h(2) = gca;
Note that the configurations of the the first handle prevail:
linkaxes(h)
1.Get the handle of your figure and the axes, like this:
%perhaps the easiest way, if you have just this one figure:
myFigHandle=gcf;
myAxHandle=gca;
%if not possible, you have to search for the handles:
myFigHandle=findobj('PropertyName',PropertyValue,...)
%you have to know some property to identify it of course...
%same for the axes!
2.Set the properties, like this:
%set units to pixels (or whatever you prefer to make it easier to compare to the other plot)
set(myFigHandle, 'Units','pixels')
set(myAxHandle, 'Units','pixels')
%set the size:
set(myFigHandle,'Position',[x_0 y_0 width height]) %coordinates on screen!
%set the size of the axes:
set(myAxHandle,'Position',[x_0 y_0 width height]) %coordinates within the figure!
Ok, based on the answer of #Lucius Domitius Ahenoba here is what I came up with:
hgload('fig1.fig'); % figure whose axis properties I would like to copy
hgload('fig2.fig');
figHandles = get(0,'Children');
figHandles = sort(figHandles,1);
ax(1) = findobj(figHandles(1),'type','axes','-not','Tag','legend','-not','Tag','Colorbar');
ax(2) = findobj(figHandles(2),'type','axes','-not','Tag','legend','-not','Tag','Colorbar');
screen_pos1 = get(figHandles(1),'Position');
axis_pos1 = get(ax(1),'Position');
set(figHandles(2),'Position',screen_pos1);
set(ax(2),'Position',axis_pos1);
This is the 'before' result:
and this is the 'after' result:
Almost correct, except that the aspect ratios are still off. Does anybody know how to equalize everything related to the axes? (I realize that I'm not supposed to ask questions when posting answers, however adding the above as a comment was proving a little unwieldy!)
I have a problem, where I already have a handle to a figure created, and I want to somehow now draw a line, given that handle. For example, I have:
f1 = figure(1);
a1 = gca;
For commands like plot and surf, I can pass the axes and/or figure handles to tell it to plot to that particular figure. However, how do you do this with the line command? There does not seem to be a way as far as I know... thank you.
The line function, like patch is a low level function. The plot command are built on top of these. However you can do this:
f1 = figure(1);
a1 = gca;
line([0 1],[0 1],'Parent',a1); % Parent has to be an axis handle
You can find more line options here: line properties or type doc Line_Props in the Matlab command window.
Have you tried the `Parent' property?
line( x, y, 'Parent', a1 );
see line properties for more info.
I am having difficulties on plotting time on the xaxis. I have some overlapping labels. See below:
This is my code:
time=datenum(0,0,0,0,0,timeinseconds);
labs=1:10:length(time);
figure(3);
plotyy(time,xvalue,time,dens);
datetick('x','HH:MM');
set(gca,'XTick',time(labs),'XTickLabel',time(labs));
legend('xval','CDF');
title('Crash on Oct.10 2008 at 15:59pm');
xlabel('Time');
First, why are the labels overlapping with the old ones? And secondly, how I can get the label to rotate 90degrees? I tried some other matlab functions to turn the labels but none seem able to tackle time format labels.
Calling plotyy you create two axis objects. Your overlap problem does probably come from the fact that you modify only one set of those axis, while leaving the other as it was originally set up.
One option is handling both of the created axis when you call plotyy by:
[AX, H1, H2] = plotyy( time, xvalue, time, dens);
Your first option here is setting up both of the axis, contained within the array of handlers AX, via changing the'XTick' propriety as:
set( AX(1), 'XTick', time(labs), 'XTickLabel', time(labs));
set( AX(2), 'XTick', time(labs), 'XTickLabel', time(labs));
But you also have the option of leaving the labels for the second axis empty, replacing the second line above:
set( AX(1), 'XTick', time(labs), 'XTickLabel', time(labs));
set( AX(2), 'XTick', time(labs), 'XTickLabel', []);
The official documentation of plotyy and Using Multiple X- and Y-Axes can be of further help for you.
If you take a look on the example there, namely, plotyy documentation:
figure
x = 0:0.01:20;
y1 = 200*exp(-0.05*x).*sin(x);
y2 = 0.8*exp(-0.5*x).*sin(10*x);
[AX,H1,H2] = plotyy(x,y1,x,y2,'plot');
and as you did before, try to modify only the AX(2), which is equivalent to what you got writing gca:
set(AX(2),'XtickLabel',1:0.1:20)
you will observe that the same overlapping error takes place.
With respect to rotating the labels 90 deg, I'm afraid that's not currently supported by Matlab. However, you can probably get that done using one of the available packages on FileExchange. Either xticklabelrotate or Rotate Tick Label could be the one.
How can I make plots in MATLAB like in below?
I won't need labels, so you can ignore them. I tried using normal 2D plot, by giving 0 to y parameter for each data points. It does help, but most of the plot remains empty/white and I don't want that.
How can I solve this problem?
Edit:
This is how I plot(playing with values of ylim does not help):
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
title('LDA 1D Plot');
ylim([-0.2 0.2]);
hold off
One way to do this would be to adjust the 'XLim', 'YLim', and 'DataAspectRatio' properties of the axes so that it renders as essentially a single line. Here's an example:
data1 = rand(1,20)./2; %# Sample data set 1
data2 = 0.3+rand(1,20)./2; %# Sample data set 2
hAxes = axes('NextPlot','add',... %# Add subsequent plots to the axes,
'DataAspectRatio',[1 1 1],... %# match the scaling of each axis,
'XLim',[0 1],... %# set the x axis limit,
'YLim',[0 eps],... %# set the y axis limit (tiny!),
'Color','none'); %# and don't use a background color
plot(data1,0,'r*','MarkerSize',10); %# Plot data set 1
plot(data2,0,'b.','MarkerSize',10); %# Plot data set 2
And you will get the following plot:
Here's one way to reproduce your figure using dsxy2figxy and annotate. dsxy2figxy can be hard to find the first time, as it is not really in your path. It is part of the MATLAB package and is provided in the example functions. You can reach it by searching for it in the help docs and once you find it, open it and save it to a folder in your path.
h1=figure(1);clf
subplot(4,1,1);
hold on
xlim([0.2,1]);ylim([-1,1])
%arrow
[arrowX,arrowY]=dsxy2figxy([0.2,1],[0,0]);
annotation('arrow',arrowX,arrowY)
%crosses
x=[0.3,0.4,0.6,0.7,0.75];
plot(x,0,'kx','markersize',10)
%pipes
p=[0.5,0.65];
text(p,[0,0],'$$\vert$$','interpreter','latex')
%text
text([0.25,0.5,0.65],[1,-1,-1]/2,{'$$d_i$$','E[d]','$$\theta$$'},'interpreter','latex')
axis off
print('-depsc','arrowFigure')
This will produce the following figure:
This is sort of a hackish way to do it, as I've tricked MATLAB into printing just one subplot. All rasterized formats (jpeg, png, etc) will not give you the same result, as they'll all print the entire figure including where the non-declared subplots should've been. So to get this effect, it has to be an eps, and it works with it because eps uses much tighter bounding boxes... so all the meaningless whitespace is trimmed. You can then convert this to any other format you want.
Ok so the closest I have come to solving this is the following
hax = gca();
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
set(hax, 'visible', 'off');
hax2 = axes();
set(hax2, 'color', 'none', 'ytick', [], 'ycolor', get(gcf, 'color');
pos = get(hax, 'position');
set(hax2, 'position', [pos(1), pos(2)+0.5*pos(4), pos(3), 0.5*pos(4)]);
title('LDA 1D Plot');
hold off
So in short, I hid the original axis and created a new one located at 0 of the original axis, and as I couldn't remove the y axis completely I set it's color to the background color of the figure.
You can then decide if you also want to play with the tick marks of the x-axis.
Hope this helps!
Very naive trick but a useful one.
Plot in 2d using matlab plot function. Then using edit figure properties compress it to whichever axis you need a 1D plot on !! Hope that helps :)