How to adjust figure size when using plotyy? - matlab

I'm trying to adjust the figure size when using plotyy:
clc;
clear all;
t = 0:.1:4*pi;
y = sin(t);
figure(1);
set(gcf,'units','inches','renderer', 'painters');
pos = get(gcf,'pos');
set(gcf,'Units','inches',...
'Position',[pos(1) pos(2) 4 2]);
plot(t,y)
xlabel('Time(s)')
ylabel('y(t)')
title('Sin function')
legend('y=sin(t)')
axis([0 t(end) -1.5 1.5])
set(gca,...
'Units','normalized',...
'YTick',-1.5:.5:1.5,...
'XTick',0:t(end)/4:t(end),...
'FontUnits','points',...
'FontWeight','normal',...
'FontSize',9,...
'FontName','Times')
set(gca, 'Position', get(gca, 'OuterPosition') - ...
get(gca, 'TightInset') * [-1 0 1 0; 0 -1 0 1; 0 0 1 0; 0 0 0 1]);
figure(2);
set(gcf,'units','inches','renderer', 'painters');
pos = get(gcf,'pos');
set(gcf,'Units','inches',...
'Position',[pos(1) pos(2) 4 2]);
[haxes,hline1,hline2]=plotyy(t,y,t,t);
ylabel(haxes(1),'sin(t)')
ylabel(haxes(2),'45degree')
xlabel(haxes(1),'Time(s)')
title('Sin function')
set(haxes,...
'Units','normalized',...
'FontUnits','points',...
'FontWeight','normal',...
'FontSize',9,...
'FontName','Times')
set(haxes(1), 'Position', get(haxes(1), 'OuterPosition') - ...
get(haxes(1), 'TightInset') * [-1 0 1 0; 0 -1 0 1; 0 0 0 0; 0 0 0 1]-...
get(haxes(2), 'TightInset') * [0 0 0 0; 0 0 0 0; 0 0 1 0; 0 0 0 0]);
The example indicates that the procedure works well for plot but not for plotyy. It seems that when I use plot, TightInset takes into account the text on the bottom and on the top (as it should), but it doesn't take them into account when I use plotyy. But I don't understand why this is the case and how to fix it. Any ideas?
[Code below is related to my comment to the chosen answer]
figure(3);
set(gcf,'units','inches','renderer', 'painters');
pos = get(gcf,'pos');
set(gcf,'Units','inches',...
'Position',[pos(1) pos(2) 4 2]);
plot(t,y,'b');
set(gca,'YColor','b')
xlabel('Time(s)')
ylabel('y(t)')
title('Sin function')
axis([0 t(end) -1.5 1.5]);
set(gca,...
'Units','normalized',...
'YTick',-1.5:.5:1.5,...
'XTick',0:t(end)/4:t(end),...
'FontUnits','points',...
'FontWeight','normal',...
'FontSize',9,...
'FontName','Times')
axesPosition = get(gca,'Position');
hNewAxes = axes('Position',axesPosition,...
'Color','none',...
'YLim',[0 10],...
'YAxisLocation','right',...
'XTick',[],...
'Box','off');
set(gca,'YColor',[0 .5 0]);
ylabel(hNewAxes,'45degree');
hold all
plot(hNewAxes,t,t,'color',[0 .5 0]);
hold off

Personally I try to avoid plotyy because there is always a property which doesn't behave as expected. If I need I usually create the second axes and set the properties by hand, copying what I need from the first axes of course, and linking a few properties.
If you look at the code for plotyy you will see that it does the same ... with some extra.
A nice extra is how it tries to match the ticks on both y axes, even when their span is different (but you could copy that part out and still use a manual dual axes solution).
Another extra, and what I suspect is responsible for the behavior you observed, is that it sets listeners and callback to readjust the position properties of both axes. Somewhere down the line it must kill some automatic readjustment of the axes because if you notice in your code, even before you tried to change the position manually, the axes were not readjusted when you called xlabel and title (as they are normally when you do that on a standard single axes).
This is why the TightInset you try to use to readjust your axes does not work ... because the axes were not readjusted when you added the text objects, (and so the vertical TightInset is wrong).
Now for your case, fortunately this only seem to affect the vertical part of the TightInset, so a quick workaround to get everything tight as in your first figure is to use the OuterPosition property for the vertical part (after getting the margin from TightInset for the horizontal part).
So in your code just replace your last call to set(haxes,'Position', ...) with:
margin = get(haxes(1),'TightInset') * [0;0;1;0] ;
set(haxes,'OuterPosition',[-margin 0 1+margin 1])
and everything should be tight again ;-)

Related

Error in MATLAB colorbar tick labeling?

I am plotting 9 subplots as shown in figure below with one color bar for three subplots.
Here I want to show the highest value in color bar as > value, surprisingly when I manually edit the tick label as h.TickLabels{end} = ['>' h.TickLabels{end}]; the color bar starts repeating the value.
When I remove h.TickLabels{end} = ['>' h.TickLabels{end}]; the color bar show no problem. When I change the figure size in set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 8 8]) as [0 0 5 5] colorbar labeling again changes.
How to resolve this error?
Below are my working example and output image:
data = [1 2 3; 5 7 3; 12 29 14; 1 7 3; 2 8 3; 5 4 1; 2 2 1; 2 3 1; 1 5 2];
for i=1:9
subplot(3, 3, i)
plot(data(i,:));
if ismember(i, [1:3])
caxis([0 20])
if i==3
h = colorbar('Fontsize', 6, 'LineWidth', 0.15, 'TickDirection', 'out',...
'TickLength', 0.02);
set(h, 'Position', [.935 .6867 .01 .2533])
h.TickLabels{end} = ['>' h.TickLabels{end}];
end
end
if ismember(i, [4:6])
caxis([0 6])
if i==6
h = colorbar('Fontsize', 6, 'LineWidth', 0.15, 'TickDirection', 'out',...
'TickLength', 0.02);
set(h, 'Position', [.935 .3733 .01 .2533])
h.TickLabels{end} = ['>' h.TickLabels{end}];
end
end
if ismember(i, [7:9])
caxis([0 4])
if i==9
h = colorbar('Fontsize',6, 'LineWidth', 0.15, 'TickDirection', 'out',...
'TickLength', 0.02);
set(h, 'Position', [.936 .06 .01 .2533])
h.TickLabels{end} = ['>' h.TickLabels{end}];
end
end
end
set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 8 8])
print('test', '-djpeg', '-r300')
close all
Why is this happening?
Manually changing the TickLabels changes the TickLabelsMode property to manual and the control gets lost for zooming/panning/resizing the figure window.
How can this be fixed?
Use a listener that will adjust the ticks itself. It may require undocumented features. You can take ideas on implementing a listener for colorbar from Yair Altman's this utility. This is for ticklabels of axes and would require some tweaking to work for colorbar.
or a relatively simpler approach would be to:
Change the 'TicksMode' to manual i.e.:
Before this line h.TickLabels{end} = ['>' h.TickLabels{end}];, include
this line:
set(h, 'Ticks', get(h,'Ticks')); %or h.Ticks = h.Ticks; for >= R2014b
This ensures that the ticks remain the same and hence the number of ticks also remains the same and therefore ticklabels will not malfunction on zooming/panning/resizing the figure window.
If you want to have more or less ticks than you originally get then set them as:
%Adjust the increment as desired. I set it as 1 (default)
set(h, 'Ticks', in1:1:in2); %or h.Ticks = in1:1:in2; for >= R2014b
%where in1 and in2 are the 1st and 2nd input args you used for caxis respectively
or if you're only concerned with the output jpeg file and your ticklabels are malfunctioned in the output image file then:
Set the PaperUnits / PaperPosition at the beginning of the plotting instead of doing that at the end. This will not automate the ticklabels but will only make the temporary adjustment.
As Sardar wrote, the only option to solve this automatically, and not lose the auto-scaling of the ticks when the figure window size is changed is to add a listener. This is how to do it:
Copy the following function to an m-file, and save it in the folder you work on this figure (i.e. your current path):
function set_cb_lables
% add '>' to the last tick label in all colorbars
h = findobj(gcf,'Type','Colorbar'); % get all colorbars handels
set(h,{'TickLabelsMode'},{'auto'}); % change thier mode to 'auto'
tiklbl = get(h,{'TickLabels'}); % get all tick labels after the change
for k = 1:numel(tiklbl)
tiklbl{k}{end} = ['>' tiklbl{k}{end}]; % add '>' to the last tick
end
set(h,{'TickLabels'},tiklbl); % replace the current ticklabels with tiklbl
end
Then, in your code, add this line after the loop:
set(gcf,'SizeChangedFcn','set_cb_lables'); % aplly the function 'set_cb_lables' upon any size change
This will add '>' automatically to the last tick label upon any resizing of the figure.
This solution is better than just getting the ticks before adding the '>' because now if the window gets bigger, the colorbar is populated automatically with more ticks.

delete a line in a for loop with MATLAB

i'm struggling with this matter probably
i'm just starting with Matlab.this is my code,i
wanna rotate a two links arm,using rotation matrix:
clear all
close all
clc
myaxes = axes('Xlim',[-1 1 ],'Ylim',[-1 1],'Zlim',[-1 1]);
view(3);
grid on;
axis equal;
hold on
xlabel('X')
ylabel('y')
zlabel('Z')
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 =(0:0.5:15) ;
for i = 1:length(alfa_1)
M3(:,:,i) = [cosd(alfa_1(i)) -sind(alfa_1(i)) 0
sind(alfa_1(i)) cosd(alfa_1(i)) 0
0 0 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5;0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1;0; 0];
figure(1)
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
hold on
M3_1(:,:,i) = [cosd(alfa_2(i)) -sind(alfa_2(i)) 0
sind(alfa_2(i)) cosd(alfa_2(i)) 0
0 0 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)],[P_1(2,i,i) P_2_2(2,i,i)],[P_1(3,i,i) P_2_2(3,i,i)],'color','r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
hold on
end
should i use delete function to obtain an animation without plotting
all the lines but only the current line?!?.
thanks in advance for your help and support.
You can use the drawnow function in MATLAB for this purpose. This function can be used inside a for loop to force a plot to be rendered every iteration, instead of being stored in a buffer until after the loop.
Update figure window and execute pending callbacks
An example: for a simpler code consider a object moves on circle
t = 0:0.05:2*pi;
x = cos(t);
y = sin(t);
for k=1:length(t)
plot(x(k),y(k),'ko')
axis([-1.2 1.2 -1.2 1.2])
axis square
drawnow
end
Please note the axis function in this method. If the axis lines are deleted from the code then, in every iteration, the axis limits will change and the animation is not smooth.
What about your code:
clear all
close all
clc
view(3);
xlabel('X');
ylabel('y');
zlabel('Z');
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 = (0:0.5:15) ;
for i = 1:length(alfa_1)
% Calculate new values for plotting
M3(:,:,i) = [cosd(alfa_1(i)), -sind(alfa_1(i)), 0
sind(alfa_1(i)), cosd(alfa_1(i)), 0
0 , 0 , 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5; 0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1; 0; 0] ;
% Clear figure 1 and hold for all plots
figure(1)
clf
% Hold only needs to be applied around plots on same axes
hold on
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
% Recalculate plotting values
M3_1(:,:,i) = [cosd(alfa_2(i)), -sind(alfa_2(i)), 0
sind(alfa_2(i)), cosd(alfa_2(i)), 0
0 , 0 , 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)], [P_1(2,i,i) P_2_2(2,i,i)], [P_1(3,i,i) P_2_2(3,i,i)], 'color', 'r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
% Set axis limits for consistency in all plots, show grid
axis([-2 2 -2 2])
grid on
% Hold off is good practice to avoid later accidental plotting on same axes
hold off
% Draw from the buffer
drawnow
end
you can save(if you want) this animation with getFrame function and play it with movie function
and another function may helps you is comet.

hide a range of color from colorbar

I have a map that contains values from 0 to 1 but also NaN contents.
I manage to defined a contour like map with the following code in MATLAB:
imagesc(map)
contourcmap('jet',[-0.3 0 0.3 0.6])
myMap = [[1 1 1]; ...
[1 0 0]; ...
[0 1 0]; ...
[0 0 1]];
colormap(myMap);
cbar = colorbar
what I get is a map like this:
however I'd like to show only red,green and blue on the colorbar and get rid of the white range (i.e., [-0.3,0)) but don't want to change the color scale on the main map. is this possible in matlab?
colorbar is an axes object and as such you can modify its properties, including the color limits. This is done through the 'YLim' property, like this:
colorbar('YLim', [0 0.6]);
Or you can modify this at any time using the object handle:
cbar = colorbar;
set(cbar, 'YLim', [0 0.6]);

Matlab - how to draw pixels on a black full screen?

I want matlab to show me a full screen, all black, and to be able to set pixels on it.
Is it even possible?
You can't totally do that using pure MATLAB code. On Windows, I tried different combinations, but the taskbar will still be on top (the one with the Start button):
%# 1)
sz = get(0, 'ScreenSize');
figure('Menubar','none', 'WindowStyle','modal', ...
'Units','pixels', 'Position', [0 0 sz(3) sz(4)])
%# 2)
figure('Menubar','none', 'Units','normalized', 'Position',[0 0 1 1])
%# 3)
hFig = figure('Menubar','none', 'Units','normalized', 'Position',[0 0 1 1]);
set(hFig, 'Units','pixels')
p = get(hFig, 'Position');
set(hFig, 'Position', [1 31 p(3) p(4)-8]);
You would have to write a MEX function and call the the Win32 API directly. Fortunately, there should be existing submissions on FEX implementing such functionality.
Here is an example of creating a full screen figure, and drawing points with the mouse. I am using the WindowAPI solution by Jan Simon
%# open fullscreen figure
hFig = figure('Menubar','none');
WindowAPI(hFig, 'Position','full');
%# setup axis
axes('Color','k', 'XLim',[0 1], 'YLim',[0 1], ...
'Units','normalized', 'Position',[0 0 1 1], ...
'ButtonDownFcn',#onClick)
The callback function:
function onClick(hObj,ev)
%# draw point
p = get(hObj,'CurrentPoint');
line(p(1,1), p(1,2), 'Color','r', 'LineStyle','none', ...
'Marker','.', 'MarkerSize',40, 'Parent',hObj)
end
Check out psychophysics toolbox. It does exactly what you are looking for and more.
Try this:
screen_size = get(0, 'ScreenSize');
buff=zeros(screen_size(3),screen_size(4));
for i=1:50
buff(screen_size(3)/2-i,screen_size(4)/2+i)=100;
end
f1 = image(buff)
colormap(gray)
set(gcf,'windowstyle','modal');
set(gcf,'OuterPosition', screen_size);
set(gcf,'position',screen_size);
set(gcf,'Units','normal', 'outerposition',[0 0 1 1])
set(gca,'Visible', 'Off', 'Position',[0 0 1 1])
Use Alt+F4 (or equivalent) to kill the window. I don't fully understand why you have to do it this way, but it is the only way I've ever found to remove the window frame and make the plot extend full screen.

How to plot 3D grid (cube) in Matlab

Hi I would like to plot transparent cube-shaped grid with lines in it. Something like this:
However, I managed only to draw a 2D grid:
[X,Y] = meshgrid(-8:.5:8);
Z = X+1;
surf(X,Y,Z)
I use Matlab R2009b.
If it is impossible to plot this in matlab could you recommend me a software I could use.
Consider this vectorized solution. It has the advantage that it creates a single graphic object:
%# these don't all have to be the same
x = -8:2:8; y = -8:2:8; z = -8:2:8;
[X1 Y1 Z1] = meshgrid(x([1 end]),y,z);
X1 = permute(X1,[2 1 3]); Y1 = permute(Y1,[2 1 3]); Z1 = permute(Z1,[2 1 3]);
X1(end+1,:,:) = NaN; Y1(end+1,:,:) = NaN; Z1(end+1,:,:) = NaN;
[X2 Y2 Z2] = meshgrid(x,y([1 end]),z);
X2(end+1,:,:) = NaN; Y2(end+1,:,:) = NaN; Z2(end+1,:,:) = NaN;
[X3 Y3 Z3] = meshgrid(x,y,z([1 end]));
X3 = permute(X3,[3 1 2]); Y3 = permute(Y3,[3 1 2]); Z3 = permute(Z3,[3 1 2]);
X3(end+1,:,:) = NaN; Y3(end+1,:,:) = NaN; Z3(end+1,:,:) = NaN;
%#figure('Renderer','opengl')
h = line([X1(:);X2(:);X3(:)], [Y1(:);Y2(:);Y3(:)], [Z1(:);Z2(:);Z3(:)]);
set(h, 'Color',[0.5 0.5 1], 'LineWidth',1, 'LineStyle','-')
%#set(gca, 'Box','on', 'LineWidth',2, 'XTick',x, 'YTick',y, 'ZTick',z, ...
%# 'XLim',[x(1) x(end)], 'YLim',[y(1) y(end)], 'ZLim',[z(1) z(end)])
%#xlabel x, ylabel y, zlabel z
axis off
view(3), axis vis3d
camproj perspective, rotate3d on
If you don't mind a few for loops, something like this will work:
clf
figure(1)
for g = 0:.2:2
for i = 0:.2:2
plot3([g g], [0 2], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([0 2], [g g], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([i i], [g g], [0 2])
hold on
end
end
You will just need to make the grid transparent by probably changing line properties, I don't think you can change alpha values to accomplish this. Hope that is helpful.
A more vectorized version of Stephen's answer might be the following:
i = 0:0.2:2;
[X Y] = meshgrid(i,i);
x = [X(:) X(:)]';
y = [Y(:) Y(:)]';
z = [repmat(i(1),1,length(x)); repmat(i(end),1,length(x))];
col = 'b';
hold on;
plot3(x,y,z,col);
plot3(y,z,x,col);
plot3(z,x,y,col);
Unfortunately, MATLAB does not currently support transparent lines (to my knowledge). If you really need them to be transparent I'd suggest using 'patch'.
I understand this is a late reply but it is still valid in case anyone else is looking at doing the same thing.
Assuming you are plotting cubes (/their edges), an alternative to the answers already provided is to use the 'plotcube' code from Oliver:
plotcube
The advantage of this solution is that you can:
Change the transparency of the faces (FaceAlpha), and/or,
Change the transparency of the edges (EdgeAlpha), and/or,
Change the colour of the lines (EdgeColor).
All of these can be constants, or variables.
(e.g. fixed edge colour, or a colour that changes with Z-value etc.)
To add in functionality of 2. and 3. (above) change the 'cellfun(#patch...' section in Olivers code, adding in the four extra lines of code as follows: (replace the whole cellfun section with this; including the new 'EdgeAlpha' and 'EdgeColor' lines):
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1),...
repmat({'EdgeAlpha'},6,1),...
repmat({0.2},6,1),... % Set this value to whatever you want; even a variable / matrix
repmat({'EdgeColor'},6,1),...
repmat({'black'},6,1)...
);
For more info on 'patch' please see patch documentation.
An important note:
- for large models (many cubes) this is very slow to run.
e.g. running this 'plotcube' function in a 'for' loop in MATLAB over thousands of blocks. I believe this is from calling the 'patch' function multiple times.
A better solution would be to vectorise; to put all your points (vertices/faces/whatever) together in a single matrix first and then call the #patch function only once (no 'for' loop). This would require changing the code somehow to update all the XYZ data.
I hope that helps someone.
Here is the 'plotcube' code in case the link to the original code by Oliver breaks someday:
function plotcube(varargin)
% PLOTCUBE - Display a 3D-cube in the current axes
%
% PLOTCUBE(EDGES,ORIGIN,ALPHA,COLOR) displays a 3D-cube in the current axes
% with the following properties:
% * EDGES : 3-elements vector that defines the length of cube edges
% * ORIGIN: 3-elements vector that defines the start point of the cube
% * ALPHA : scalar that defines the transparency of the cube faces (from 0
% to 1)
% * COLOR : 3-elements vector that defines the faces color of the cube
%
% Example:
% >> plotcube([5 5 5],[ 2 2 2],.8,[1 0 0]);
% >> plotcube([5 5 5],[10 10 10],.8,[0 1 0]);
% >> plotcube([5 5 5],[20 20 20],.8,[0 0 1]);
% Default input arguments
inArgs = { ...
[10 56 100] , ... % Default edge sizes (x,y and z)
[10 10 10] , ... % Default coordinates of the origin point of the cube
.7 , ... % Default alpha value for the cube's faces
[1 0 0] ... % Default Color for the cube
};
% Replace default input arguments by input values
inArgs(1:nargin) = varargin;
% Create all variables
[edges,origin,alpha,clr] = deal(inArgs{:});
XYZ = { ...
[0 0 0 0] [0 0 1 1] [0 1 1 0] ; ...
[1 1 1 1] [0 0 1 1] [0 1 1 0] ; ...
[0 1 1 0] [0 0 0 0] [0 0 1 1] ; ...
[0 1 1 0] [1 1 1 1] [0 0 1 1] ; ...
[0 1 1 0] [0 0 1 1] [0 0 0 0] ; ...
[0 1 1 0] [0 0 1 1] [1 1 1 1] ...
};
XYZ = mat2cell(...
cellfun( #(x,y,z) x*y+z , ...
XYZ , ...
repmat(mat2cell(edges,1,[1 1 1]),6,1) , ...
repmat(mat2cell(origin,1,[1 1 1]),6,1) , ...
'UniformOutput',false), ...
6,[1 1 1]);
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1)...
);
view(3);
you can make the inside line kind of transparent by setting color = [0.65, 0.65, 0.65]. And you can use dash line style for interior lines and solid lines for boundary to make it more like a 3-D object.
In my software package, I code a mesh3 function to plot the 3-D tensor product meshes.
clear all
close all
clc
Nx=11;
Ny=11;
Nz=11;
clf
hold on
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+Nz;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+Ny;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+Nx;
surf(i,j,k)
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+1;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+1;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+1;
surf(i,j,k)
view(30,30)