Missing axes in figure with multiple subplots - matlab

I am drawing a figure with multiple subplots with the following code
w = 7;
h = 5;
figure;
m = 0.005;
for n = 1:w*h
[I, J] = ind2sub([w, h], n);
pos = [(I-1)/w+m, (J-1)/h+m, 1/w-2*m, 1/h-2*m];
h_axes = subplot(h, w, n, 'position', pos);
imagesc(rand(10), 'Parent', h_axes);
axis(h_axes, 'image')
axis(h_axes, 'off')
end
However, only the top two rows are plotted, whereas 5 rows are expected. Going through this code step by step, it seems that lower rows are initially drawn but later upper rows erase them. The axes handles are invalidated, so the axes are not simply hidden but really deleted. Any idea what is going on?

There is a problem with the way you use subplot. You can use either syntax:
subplot(m,n,p)
or
subplot('Position',positionVector)
... but not both in the same call.

Related

I want to plot lines and dots and add legend only for lines on matlab [duplicate]

t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
hold on;
plot(t, s, 'r');
plot(t, c, 'b');
plot(t, m, 'g');
hold off;
legend('', 'cosine', '');
There are several curves in my plotting. I want to display legend for only some of them. How do I do it?
For example, how do I make only the legend for the cosine curve visible in the plotting above? When I call the legend() functions as legend('', 'cosine'); instead of adding the empty third parameter, indeed the third green line is removed from the legend. But that doesn't solve my problem, because the undesired red line stays visible.
I do not like storing the handle values, it becomes a mess when I have a lot of graphs in my figures. Therefore i found another solution.
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
hold on;
plot(t, s, 'r', 'HandleVisibility','off'); % Plotting and telling to hide legend handle
h2 = plot(t, c, 'b', 'DisplayName', 'cosine'); % Plotting and giving legend name
plot(t, m, 'g', 'HandleVisibility','off'); % Plotting and telling to hide legend handle
legend show % Generating legend based on already submitted values
This give me the same graph as shown in Eitan T's answer.
It should be noted that this will affect other matlab functions also, for example will cla only remove the plots mentioned on the legend. Search for HandleVisibility in the Matlab documentation for more about that.
Just store the desired legend handles in a variable and pass the array to legend. In your case, it would only be one value, like so:
hold on;
plot(t, s, 'r');
h2 = plot(t, c, 'b'); % # Storing only the desired handle
plot(t, m, 'g');
hold off;
legend(h2, 'cosine'); % # Passing only the desired handle
You should get this plot:
Let's start with your variables and plot them:
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
figure;
hold ('all');
hs = plot(t, s);
hc = plot(t, c);
hm = plot(t, m);
There is a property called IconDisplayStyle. It is buried quite deep. The path you need to follow is:
Line -> Annotation -> LegendInformation -> IconDisplayStyle
Setting the IconDisplayStyle property off will let you skip that line. As an example, I am going to turn off hs's legend.
hsAnno = get(hs, 'Annotation');
hsLegend = get(hsAnno, 'LegendInformation');
set(hsLegend, 'IconDisplayStyle', 'off');
Of course you can go ahead and do it like this:
set(get(get(hs, 'Annotation'), 'LegendInformation'), 'IconDisplayStyle', 'off');
But I find it much harder to understand.
Now, the legend function will just skip hs.
Ending my code with this:
legend('cosine', 'repeat for this handle')
will give you this:
EDIT: Jonas had a nice suggestion in the comments:
Setting the DisplayName property of hc like this:
set(hc, 'DisplayName', 'cosine');
legend(gca, 'show');
will give you the legend you need. You will have associated your line handle with 'cosine'. So, you can just call the legend with 'off' or 'show' parameters.
You could just change the order in wich the curves are plotted and apply the legend to the first curve:
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
plot(t,c,t,s,t,m) % cosine is plotted FIRST
legend('cosine') % legend for the FIRST element
if i'd want to put in a legend for cosine and -sine:
plot(t,c,t,m,t,s) % cosine and -sine are first and second curves
legend('cosine', '-sine')
To expand Sebastian's answer, I have a special case where I'm plotting several lines in one of two formats (truss beams either in compression or tension) and was able to plot specific plot handles in the legend as long as the labels were the same length
for ii=1:nBeams
if X(ii)<0 %Bars with negative force are in compession
h1=plot(linspace(beamCord(ii,1),beamCord(ii,3)),...
linspace(beamCord(ii,2),beamCord(ii,4)),'r:');
elseif X(ii)>0 %Bars with positive force are in tension
h2=plot(linspace(beamCord(ii,1),beamCord(ii,3)),...
linspace(beamCord(ii,2),beamCord(ii,4)),'b');
end
end
legend([h1;h2],['Compression';'Tension ']);
Where 4 spaces have been added behind 'Tension' so that the number of characters is consistent.
Quick in-plot hack:
Cut everything you don't want to appear in the legend
Apply legend
Paste

MATLAB - adding plot to another plot after loop, more sophisticatedly

i have a problem and i hope that i will find help there.
This is my example code. Its only part of my algorithm. For imagine, how the point are moving, during the equations, i need show contour of function with two variables and into the points. Becase i have more difficult function than parabolic function, so the equations are too long than i need. For this reason i move contour ploting before the loop. But i have problem. I need show countour always and points only for i-loop and my solution doesnt work. Please help me!
[R S] = meshgrid(-5:0.1:5, -5:0.1:5);
figure
contour(R, S, R.^2 + S.^2, 5);
axis([-5,5,-5,5])
axis square
hold on
for i=1:50
a = 0;
b = 1:2
B = repmat(b,5,1)
A = unifrnd(a,B)
x = A(1:5,1);
y = A(1:5,2);
scatter(x,y,'fill')
hold off
pause(0.5)
end
You should store the handle to your scatter plot and simply update the XData and YData properties of it rather than destroying the plot objects every time
[R S] = meshgrid(-5:0.1:5, -5:0.1:5);
figure
contour(R, S, R.^2 + S.^2, 5);
axis([-5,5,-5,5])
axis square
hold on
% Create a scatter plot and store the graphics handle so we can update later
hscatter = scatter(NaN, NaN, 'fill');
for i=1:50
a = 0;
b = 1:2
B = repmat(b,5,1)
A = unifrnd(a,B)
x = A(1:5,1);
y = A(1:5,2);
% Update the X and Y positions of the scatter plot
set(hscatter, 'XData', x, 'YData', y);
pause(0.5)
end

Skipping a legend in a plot loop [duplicate]

t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
hold on;
plot(t, s, 'r');
plot(t, c, 'b');
plot(t, m, 'g');
hold off;
legend('', 'cosine', '');
There are several curves in my plotting. I want to display legend for only some of them. How do I do it?
For example, how do I make only the legend for the cosine curve visible in the plotting above? When I call the legend() functions as legend('', 'cosine'); instead of adding the empty third parameter, indeed the third green line is removed from the legend. But that doesn't solve my problem, because the undesired red line stays visible.
I do not like storing the handle values, it becomes a mess when I have a lot of graphs in my figures. Therefore i found another solution.
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
hold on;
plot(t, s, 'r', 'HandleVisibility','off'); % Plotting and telling to hide legend handle
h2 = plot(t, c, 'b', 'DisplayName', 'cosine'); % Plotting and giving legend name
plot(t, m, 'g', 'HandleVisibility','off'); % Plotting and telling to hide legend handle
legend show % Generating legend based on already submitted values
This give me the same graph as shown in Eitan T's answer.
It should be noted that this will affect other matlab functions also, for example will cla only remove the plots mentioned on the legend. Search for HandleVisibility in the Matlab documentation for more about that.
Just store the desired legend handles in a variable and pass the array to legend. In your case, it would only be one value, like so:
hold on;
plot(t, s, 'r');
h2 = plot(t, c, 'b'); % # Storing only the desired handle
plot(t, m, 'g');
hold off;
legend(h2, 'cosine'); % # Passing only the desired handle
You should get this plot:
Let's start with your variables and plot them:
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
figure;
hold ('all');
hs = plot(t, s);
hc = plot(t, c);
hm = plot(t, m);
There is a property called IconDisplayStyle. It is buried quite deep. The path you need to follow is:
Line -> Annotation -> LegendInformation -> IconDisplayStyle
Setting the IconDisplayStyle property off will let you skip that line. As an example, I am going to turn off hs's legend.
hsAnno = get(hs, 'Annotation');
hsLegend = get(hsAnno, 'LegendInformation');
set(hsLegend, 'IconDisplayStyle', 'off');
Of course you can go ahead and do it like this:
set(get(get(hs, 'Annotation'), 'LegendInformation'), 'IconDisplayStyle', 'off');
But I find it much harder to understand.
Now, the legend function will just skip hs.
Ending my code with this:
legend('cosine', 'repeat for this handle')
will give you this:
EDIT: Jonas had a nice suggestion in the comments:
Setting the DisplayName property of hc like this:
set(hc, 'DisplayName', 'cosine');
legend(gca, 'show');
will give you the legend you need. You will have associated your line handle with 'cosine'. So, you can just call the legend with 'off' or 'show' parameters.
You could just change the order in wich the curves are plotted and apply the legend to the first curve:
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
plot(t,c,t,s,t,m) % cosine is plotted FIRST
legend('cosine') % legend for the FIRST element
if i'd want to put in a legend for cosine and -sine:
plot(t,c,t,m,t,s) % cosine and -sine are first and second curves
legend('cosine', '-sine')
To expand Sebastian's answer, I have a special case where I'm plotting several lines in one of two formats (truss beams either in compression or tension) and was able to plot specific plot handles in the legend as long as the labels were the same length
for ii=1:nBeams
if X(ii)<0 %Bars with negative force are in compession
h1=plot(linspace(beamCord(ii,1),beamCord(ii,3)),...
linspace(beamCord(ii,2),beamCord(ii,4)),'r:');
elseif X(ii)>0 %Bars with positive force are in tension
h2=plot(linspace(beamCord(ii,1),beamCord(ii,3)),...
linspace(beamCord(ii,2),beamCord(ii,4)),'b');
end
end
legend([h1;h2],['Compression';'Tension ']);
Where 4 spaces have been added behind 'Tension' so that the number of characters is consistent.
Quick in-plot hack:
Cut everything you don't want to appear in the legend
Apply legend
Paste

Larger subplots in MATLAB

I have 6 Y variables all with the same X Variable (time)
I want to have 6 plots in a column but when I use subplot(6,1,1) the plots become tiny vertically.
I have tried using:
x=0:360;
y1=sind(x);
y2=cosd(x);
h=subplot(6,1,1);
plot(x,y1);
d = get(h,'Position');
d(4)=d(4)*3;
set(h,'Position',d);
h=subplot(6,1,2);
plot(x,y2);
d = get(h,'Position');
d(4)=d(4)*3;
set(h,'Position',d);
....(For 6 subplots)
In the hope that each subplot would be 3 times larger vertically, which works but the spacing between the subplots does not update so the subplots start to overlap:
How can I make it so the subplots are larger vertically but equally spaced out like they were before I changed the height of each subplot?
Also if you could help me hide the xTick labels (numbers) but keep the ticks (lines) themselves on all subplots but the very bottom one that would also be a great help. Thanks!
Matlab sucks pretty hard for easily making this kind of graphs. You either have to do it by hand or search around on the file-exchange to see if someone already implemented something better.
This blog discussed one script that seems to do what you want.
To hide the tick labels:
set(gca, 'XTickLabel', '')
If you want to build your own subplot, you can use something like this (not tested very well):
function ax = mySubplot(nrow, ncol)
% returns a matrix of axis handles
% to plot in the second subplot, you would use plot(ax(1,2), x, y)
% standard x, y, dx, dy for subplot(111)
x0 = 0.1300;
y0 = 0.1100;
w0 = 0.7750;
h0 = 0.8150;
w = w0 / ncol;
h = h0 / nrow;
figure()
ax = nan(nrow, ncol);
for irow = 1:nrow
for icol = 1:ncol
ax(irow, icol) = axes('position', ...
[x0 + (icol - 1) * w, y0 + (nrow - irow) * h, 0.9*w, 0.9*h]);
end
end
Result of mySubplot(6,2):
You could play yourself with the spacings.

How to show legend for only a specific subset of curves in the plotting?

t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
hold on;
plot(t, s, 'r');
plot(t, c, 'b');
plot(t, m, 'g');
hold off;
legend('', 'cosine', '');
There are several curves in my plotting. I want to display legend for only some of them. How do I do it?
For example, how do I make only the legend for the cosine curve visible in the plotting above? When I call the legend() functions as legend('', 'cosine'); instead of adding the empty third parameter, indeed the third green line is removed from the legend. But that doesn't solve my problem, because the undesired red line stays visible.
I do not like storing the handle values, it becomes a mess when I have a lot of graphs in my figures. Therefore i found another solution.
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
hold on;
plot(t, s, 'r', 'HandleVisibility','off'); % Plotting and telling to hide legend handle
h2 = plot(t, c, 'b', 'DisplayName', 'cosine'); % Plotting and giving legend name
plot(t, m, 'g', 'HandleVisibility','off'); % Plotting and telling to hide legend handle
legend show % Generating legend based on already submitted values
This give me the same graph as shown in Eitan T's answer.
It should be noted that this will affect other matlab functions also, for example will cla only remove the plots mentioned on the legend. Search for HandleVisibility in the Matlab documentation for more about that.
Just store the desired legend handles in a variable and pass the array to legend. In your case, it would only be one value, like so:
hold on;
plot(t, s, 'r');
h2 = plot(t, c, 'b'); % # Storing only the desired handle
plot(t, m, 'g');
hold off;
legend(h2, 'cosine'); % # Passing only the desired handle
You should get this plot:
Let's start with your variables and plot them:
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
figure;
hold ('all');
hs = plot(t, s);
hc = plot(t, c);
hm = plot(t, m);
There is a property called IconDisplayStyle. It is buried quite deep. The path you need to follow is:
Line -> Annotation -> LegendInformation -> IconDisplayStyle
Setting the IconDisplayStyle property off will let you skip that line. As an example, I am going to turn off hs's legend.
hsAnno = get(hs, 'Annotation');
hsLegend = get(hsAnno, 'LegendInformation');
set(hsLegend, 'IconDisplayStyle', 'off');
Of course you can go ahead and do it like this:
set(get(get(hs, 'Annotation'), 'LegendInformation'), 'IconDisplayStyle', 'off');
But I find it much harder to understand.
Now, the legend function will just skip hs.
Ending my code with this:
legend('cosine', 'repeat for this handle')
will give you this:
EDIT: Jonas had a nice suggestion in the comments:
Setting the DisplayName property of hc like this:
set(hc, 'DisplayName', 'cosine');
legend(gca, 'show');
will give you the legend you need. You will have associated your line handle with 'cosine'. So, you can just call the legend with 'off' or 'show' parameters.
You could just change the order in wich the curves are plotted and apply the legend to the first curve:
t = 0 : 0.01 : 2 * pi;
s = sin(t);
c = cos(t);
m = -sin(t);
plot(t,c,t,s,t,m) % cosine is plotted FIRST
legend('cosine') % legend for the FIRST element
if i'd want to put in a legend for cosine and -sine:
plot(t,c,t,m,t,s) % cosine and -sine are first and second curves
legend('cosine', '-sine')
To expand Sebastian's answer, I have a special case where I'm plotting several lines in one of two formats (truss beams either in compression or tension) and was able to plot specific plot handles in the legend as long as the labels were the same length
for ii=1:nBeams
if X(ii)<0 %Bars with negative force are in compession
h1=plot(linspace(beamCord(ii,1),beamCord(ii,3)),...
linspace(beamCord(ii,2),beamCord(ii,4)),'r:');
elseif X(ii)>0 %Bars with positive force are in tension
h2=plot(linspace(beamCord(ii,1),beamCord(ii,3)),...
linspace(beamCord(ii,2),beamCord(ii,4)),'b');
end
end
legend([h1;h2],['Compression';'Tension ']);
Where 4 spaces have been added behind 'Tension' so that the number of characters is consistent.
Quick in-plot hack:
Cut everything you don't want to appear in the legend
Apply legend
Paste