Individual line and axes styles with plotyy - matlab

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.

Related

MATLAB: misaligned boxes in plotyy after saving as fig

I use plotyy to put two plots in one graph:
f = figure('Color','white');
[ax,p1,p2] = plotyy(xx, yy1, xx, yy2);
ylabel(ax(1),'Phase','FontSize',18);
ylabel(ax(2),'Spectrum','FontSize',18);
set(ax,{'ycolor'},{'k';'k'});
set(p1,'LineWidth',2,'Color',[0.4940,0.1840,0.5560]);
set(p2,'LineWidth',2,'Color','red');
xlabel(ax(1),['Frequency [THz]'],'FontSize',18);
set(ax,'FontSize',14)
Figure is displayed perfectly, but when I try to save it as fig something like misaligned boxes appears.
I tried to use linkaxes, but with no result.
plotyy has been one of my favorite MATLAB functions to love to hate. It's a really useful function that I always seem to run into bugs with, to the point where I've completely stopped using it in favor of just stacking two (or more) axes objects and plotting to them separately. You can then set the Position property of the 'sub' axes to the same as your primary axes and they will stack nicely.
A functional example:
xx = linspace(-15,15,100);
yy1 = sin(xx);
yy2 = cos(xx);
f = figure('Color','white');
ax(1) = axes('Parent', f);
ax(2) = axes('Parent', f, 'Color', 'none', 'XTick', [], 'YAxisLocation', 'right');
p1 = plot(ax(1), xx, yy1);
hold(ax(2), 'on'); % Hold to preserve our axes properties set above
p2 = plot(ax(2), xx, yy2);
hold(ax(2), 'off');
ylabel(ax(1),'Phase','FontSize',18);
ylabel(ax(2),'Spectrum','FontSize',18);
set(ax,{'ycolor'},{'k';'k'});
set(p1,'LineWidth',2,'Color',[0.4940,0.1840,0.5560]);
set(p2,'LineWidth',2,'Color','red');
xlabel(ax(1),'Frequency [THz]','FontSize',18);
set(ax,'FontSize',14)
set(ax, 'ActivePositionProperty', 'position'); % Resize based on position rather than outerposition
set(ax(2), 'Position', get(ax(1), 'Position')); % Set last to account for any annotation changes
Along with stacking the axes you will also note that I have set the ActivePositionProperty to position (rather than outerposition). MATLAB resizes axes automatically when the Units property is set to Normalized, and it seems like this is the main spot where the issue is arising. On resizing, MATLAB also modifies the OuterPosition value for the second axes, causing it to resize the plot portion. The difference is small, [0 0 1 1] vs. [0 0.0371 1.0000 0.9599] in my case, but the effect is obviously very pronounced. You can use get and set to fix this, but you'll have to do it on every resize which is fairly annoying. The alternative is to resize based on the Position, which seems to alleviate the issue and is a tweak present in the R2015b implementation of plotyy. This also fixes plotyy except for cases where the window is very small, so I have left my answer with the more generic approach.

Resizing of axes when plotting in the same figure

Please, create two functions to be able to reproduce what I mean:
First function:
function testPlot1()
pointData = rand(20000,3);
figure;
%hold on; % <- if commented out, does not work
plot3(pointData(:,1), pointData(:,2), pointData(:,3),'Marker', '.', 'MarkerEdgeColor', 'b','MarkerSize', 5, 'LineStyle', 'none');
axis equal;
xh = xlabel('X');
yh = ylabel('Y');
zh = zlabel('Z');
set([xh,yh, zh],...
'fontweight','bold',...
'fontsize',14,...
'color',[0,0,0]);
view(0,20);
end
Second function:
function testPlot2(fighandle)
axes(fighandle);
hold on;
plot3([0 3],[0 3],[0 3], 'r', 'LineWidth', 10);
end
If you now call
testPlot1();testPlot2(gca)
you will get the following:
If you however uncomment the "hold on" line in testPlot1() and call the above statement again, you will get:
To me this is unclear behavior. In the first case, testPlot1() creates a figure, draws the point cloud into it and modifies the axes properties. Then the call to testPlot2(gca) adds the line to the figure, but the line is clipped.
In the second case however the line is not clipped anymore. Why is it now not clipped and previously it was?
It seems to be related to the changes I make in the axes properties in testPlot1(). Could somebody explain this behavior to me? (why does it work with hold on, what do my changes in the axes properties cause)
hold on is a Matlab command (hold off turns it off again), where you can draw multiple elements on a single figure without the previous elements being erased.
What happens
If you call the plot function, a figure is created (or an already exisiting figure is used!) and Matlab draws a new plot into that figure. The previous plot that was in that figure is gone.
If you want to add more points to your plot, you can call hold on and then call plot again, this time with different numbers and maybe a different colour or so.
However, if you forget to turn hold off again for the active figure, any drawing activity you do (like plot) will be added to the figure. This is what happens in your second image in your question. You drew some points in the range 0 to 1, and then in the second function, you add some more but in the range 2 to 3. As a result, the axes expand to the range of 0 to 3.
Alternatively, you can call figure, which will cause a new figure to appear. figure_handle = figure(); will return a figure handle, which you can pass to your function, in case you have multiple figures and want to change one of them after a while.

setting the properties of different plots at once in matlab

In a m-file, I am plotting 16 different types of plots (not in a loop). Is it possible to set the following properties of all the plots by writing only once:
set(gca,'linewidth',1,'fontsize',12);
set([xh, yh, th],'fontsize',12);
It turns out that the answer is yes, which can be easily checked e.g. using this code
figure
xh = gca;
figure
yh = gca;
set([xh, yh], 'fontsize', 12, 'linewidth', 1);
Note that the 'linewidth' property of an axes applies to the lines that make up the axes, not to any lines plotted into it. If you want to change their properties, you have to either collect the handles of all the line objects, or search for line objects later using
lh = findobj(0, 'Type', 'line');
set(lh, 'linewidth', 1)
Here '0' refers to the root object, of which all figures are children.
You can change default plotting parameters:
set(0,'DefaultLineLineWidth',1);
set(0,'DefaultAxesFontSize', 12);
set(0,'DefaultTextFontSize', 12);
Yes, it is meant to be "LineLine", it's to distinguish it from DefaultPatchLineWidth. Once you change these, it will only affect new figure windows; if you have already created the plots, use the answer given by A. Donda.

How to plot graphs above each other in Matlab?

I want to plot two (or more) graphs in Matlab. I want them to be aligned one above the second one above the third and so on. However subplot is not the case for me. I also don't want them both to be on the same graph in different colors, just to be one above the other. Is it possible? I'm searching for such a command but without any success.
Thanks in advance for hints!
If what you mean by "one above the other" is one "on top of another" then I think what You need to use is the axes command. Having said that, in order to have your plot be readable, I think more than two scales in the same plot makes it pretty hard to read.
This Matlab's help page shows you how to do it, the gist of it is shown in the following script:
y2 = 1000.*rand(100,1);
x2 = 0:99;
% Plot the first data set
hl1 = line(x1,y1,'Color','r');
% Get the axes and configure it
ax1 = gca;
set(ax1,'XColor','r','YColor','r')
%Create the new axes
ax2 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k','YColor','k');
% Plot the second data set with the new axes
hl2 = line(x2,y2,'Color','k','Parent',ax2);
The above script creates the following plot with one set of axes in red and another in black.
Hope this helps.

How to make 1-D plots in MATLAB?

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 :)