x-axis labels move to top of graph after using - matlab

I am using Rotate Tick Label to change the labels on the x-axis to a vertical orientation.
Before using the rotate tick label function the labels on the x-axis are on the bottom of the graph:
After the following command:
TH= rotateTickLabel(gca,90);
the graph looks like this:
How do I get the labels to stay on the bottom of the graph and not move to the top?

The reason why you get this error is because on plots made with 'plot' the YTicks are defined from bottom up. And on image plots (made with 'image') the YTicks are defined from top down. Make the following two changes to rotateticklabel.m:
Edit line 54 so that it looks like this:
th=text(b,repmat(c(end)-.1*(c(end-1)-c(end)),length(b),1),a,'HorizontalAlignment','right','rotation',rot);
Edit line 56 to look like this:
th=text(b,repmat(c(end)-.1*(c(end-1)-c(end)),length(b),1),a,'HorizontalAlignment','left','rotation',rot);
For completion, the entire rotateticklabel.m should look like this:
function th=rotateticklabel(h,rot,demo)
%ROTATETICKLABEL rotates tick labels
% TH=ROTATETICKLABEL(H,ROT) is the calling form where H is a handle to
% the axis that contains the XTickLabels that are to be rotated. ROT is
% an optional parameter that specifies the angle of rotation. The default
% angle is 90. TH is a handle to the text objects created. For long
% strings such as those produced by datetick, you may have to adjust the
% position of the axes so the labels don't get cut off.
%
% Of course, GCA can be substituted for H if desired.
%
% TH=ROTATETICKLABEL([],[],'demo') shows a demo figure.
%
% Known deficiencies: if tick labels are raised to a power, the power
% will be lost after rotation.
%
% See also datetick.
% Written Oct 14, 2005 by Andy Bliss
% Copyright 2005 by Andy Bliss
%DEMO:
if nargin==3
x=[now-.7 now-.3 now];
y=[20 35 15];
figure
plot(x,y,'.-')
datetick('x',0,'keepticks')
h=gca;
set(h,'position',[0.13 0.35 0.775 0.55])
rot=90;
end
%set the default rotation if user doesn't specify
if nargin==1
rot=90;
end
%make sure the rotation is in the range 0:360 (brute force method)
while rot>360
rot=rot-360;
end
while rot<0
rot=rot+360;
end
%get current tick labels
a=get(h,'XTickLabel');
%erase current tick labels from figure
set(h,'XTickLabel',[]);
%get tick label positions
b=get(h,'XTick');
c=get(h,'YTick');
%make new tick labels
if rot<180
th=text(b,repmat(c(end)-.1*(c(end-1)-c(end)),length(b),1),a,'HorizontalAlignment','right','rotation',rot);
else
th=text(b,repmat(c(end)-.1*(c(end-1)-c(end)),length(b),1),a,'HorizontalAlignment','left','rotation',rot);
end
Once you edit rotateticklabel.m you can now successfully use it on plots made with 'image' as in this short example:
A = magic(5);
image(A)
datetick('x',0,'keepticks')
h=gca;
set(h,'position',[0.13 0.35 0.775 0.55])
rot=90;
th = rotateticklabel(h,30)

Related

matlab - set tick label at origin

In generating plots with Matlab, when both the x and y minimum are zero, I prefer to have only one zero marking the origin rather than denoting it on both axes.
Matlab defaults to the latter, like so
Whereas I want something more like this
This can be done manually, but I'm trying to automate the process. Removing the x and y tick labels for 0 are obviously easy enough. However, I can't seem to access any handle for the position of the axis tick labels to properly position a text box for the 'new origin'. It seems the tick label offsets from the x and y axes may be somewhat constant in a given figure (in physical units, not normalized units), but I don't know if this is a standard across all figures or axes.
Any ideas?
I'm running Matlab 2014b.
Here's a simple way to do that:
% somthing to plot:
x = 0:0.1:2*pi;
y = abs(sin(x)+cos(x));
plot(x,y)
% get the handle for the current axes:
ax = gca;
% get the position of the zero tick on y-axis:
zeroYtick = ax.YAxis.TickValues==0;
% remove it (tick and lable)
ax.YAxis.TickValues(zeroYtick) = [];
The result:
If you want the 0 to be offset a little to the left, so it will be at the corner of the plot, you can use annotation:
% get the position of the zero tick on x-axis:
zeroXtick = ax.XAxis.TickValues==0;
% remove it (tick and lable)
ax.XAxis.TickValues(zeroXtick) = [];
% place a new zero at the origin:
dim = [0.1 0.01 0.1 0.1];
annotation('textbox',dim,'String','0',...
'FitBoxToText','on','LineStyle','none')
And you will get:
The advantage in annotation is that the origin always placed relative to the corner of the axes, and you don't need to know the values of the axes ticks to properly offset it.
EDIT:
For pre 2016a version you can use the following (I wrote it a little more compact):
ax = gca;
% remove the zero tick on y-axis (tick and lable):
ax.YTick(ax.YTick==0) = [];
% remove the zero tick on x-axis (tick and lable):
ax.XTick(ax.XTick==0) = [];
% place a new zero at the origin:
dim = [0.1 0.01 0.1 0.1];
annotation('textbox',dim,'String','0',...
'FitBoxToText','on','LineStyle','none')
EDIT 2:
Another option to keep the 0 in place is to stick it to the axes. this is done by replacing the Parent with the axes handle. First, we need a handle to the annotation (continuing from the last edit):
t = annotation('textbox',dim,'String','0',...
'FitBoxToText','on','LineStyle','none');
then we switch the Parent and set the new position:
t.Parent = ax;
t.Position(1:2) = -[0.2 0.1];
and finally, we super-glue it by converting the Units to pixels:
t.Units = 'Pixels';
The following will exclude the first tick on yaxis without shifting the graph at all. You can ensure that the correct item is being removed by setting the axis limits, ylim([0,upper_limit]) prior to removing the first one, or manually setting your yTicks, set(h,'yTick',my_ticks). Note that yTick changes the position of the ticks, while yTickLabel will change the text appearing at each position of yTick
h = plot([0,1],[0,1]);
yTicks = get(h,'yTick');
set(h,'yTick',yTick(2:end));

MATLAB: issue with putting x and y labels on each side of a plot

Based code from here, I wrote a function which plots a figure and puts x-axis labels on both the top and bottom of the figure, as well as y-axis labels on the left and right side. My problem is that I need to run the code multiple times and each time the labels get written over, and for some reason the y-axis labels get overwritten in a weird way as shown,
first run:
second run:
The following is an mwe:
% sample data, plot
x=[1:168];
y=x;
plot(x, y, 'r', 'LineWidth', 1);
set(gca, 'XTick', [], 'YTick', []);
% set left yaxis label
ylabel(directions{1,1},'Rotation',-360);
% Adjust position - this seems to be what's causing the issue!
ylabelh = get(gca,'YLabel');
rpos = get(ylabelh,'Position');
set(ylabelh,'Position',rpos + [1.5*rpos(1) 0 0])
% do stuff... as per link above
axesPosition = get(gca,'Position');
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Color','none',... %# ... with no background color
'YAxisLocation','right',... %# ... located on the right
'XTick',[],'YTick',[],... %# ... with no x tick marks
'Box','off');
ylabel(hNewAxes,directions{2,1},'Rotation',-360); % yaxis label right
% Adjust position
ylabelh = get(gca,'YLabel');
Lpos = get(ylabelh,'Position');
set(gca,'YTick',[]);
set(ylabelh,'Position',Lpos+ [+Lpos(1)*0.02 0.05 0])
% -- And repeat for x axis -- %
% x axis labels
xlabel(directions{3,1},'Rotation',-360); % xaxis label bottom
% Adjust position
xlabelh = get(gca,'XLabel');
xlabpos = get(xlabelh,'Position');
set(gca,'XTick',[]);
rpos = get(xlabelh,'Position');
% do stuff ... as above
axesPosition = get(gca,'Position');
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Color','none',... %# ... with no background color
'XAxisLocation','top',... %# ... located on the right
'XTick',[],'YTick',[], ... %# ... with no x tick marks
'Box','off');
% xaxis label top
xlabel(hNewAxes,directions{4,1},'Rotation',-360);
Weirdly, if I run the code as a script it's fine (well, the labels get written over but I don't see the issue with the y axis labels) but if I run as a function multiple times in debug mode (which is currently the primary way I'm using it) then I see the above artefacts.
If you run your code then check at the end you will see that you have created 3 axes in your script. Run it once and they type get(gcf,'Children'). If you run it again you are adding another 2 axes, this continues everytime you run it.
Why does this happen?
Well your code creates 2 new axes handles (which you call the same name -> which you shouldn't do) - but only after you have already used gca -> i.e. the current axes (if none exists one is created).
I would advise you to completly reconfigure you code. Start by creating 2 axes before you do any plotting/labeling etc.. store the 2 axes variables independently which will allow you to refer to them as and when you need to.
Also it good practice to never rely on gca or gcf to get the currently axes or figure -> as it will eventually come back to bite you. Store the axes/figure handles and refer to them explicitly.

How to subplot + imagesc with a Position in Matlab?

Situation: change Position of a single subplot with imagesc
%% Matlab recommends this structure if axes(); in loop
a1 = subplot(1,2,1);
a2 = subplot(1,2,2);
while 1    
plot(a1, rand(3))    
plot(a2, rand(3))    
drawnow
end
%% Test code
unitsPerInches=[0 0 15 15];
figure('Units', 'inches');
a1 = subplot(1,2,1);
a2 = subplot(1,2,2);
while 1    
set(a1, 'Position', unitsPerInches); % TODO how to affect a1's Position here only?
imagesc(a1, rand(3))    
imagesc(a2, rand(3))    
drawnow
end
Open
What is imagesc corresponding structure to plot(a1,rand(3))?
How to change Position of figure inside the loop?
Forward in Q1 - almost done
%% Extension to imagesc
figure
a1=subplot(1,2,1);
a2=subplot(1,2,2);
for counter=1:2;
imagesc(a1,rand(3))
imagesc(a2,rand(3))
drawnow
end
Fig. 1 Output of Docs example, Fig. 2 Output of Imagesc, Fig. 3 about Q2 where Position affects both subplots
Q1 is almost done; I have just forgotten how to get corresponding plot in imagesc; x-values should be put there but pseudocode imagesc(a1,XDATA,rand(3)) is unsuccessfuly.
Backward in Q2
Code
%% Extension to imagesc
unitsPerInches=[0 0 15 15];
figure
a1=subplot(1,2,1);
a2=subplot(1,2,2);
for counter=1:2;
set(a1, 'Position', unitsPerInches); % TODO how to affect a1's Position here only?
imagesc(a1,rand(3))
imagesc(a1,rand(3))
drawnow
end
Output: position affects both images in Fig. 3.
I think I have misunderstood the meaning of Position here because so strange output.
Testing EBH's proposal for Q2
The implicit assignments cause problems when having two figures where subplots
unitsPerInches=[0 0 15 15];
aFig=figure();
a1=subplot(1,2,1);
a2=subplot(1,2,2);
bFig=figure();
b1=subplot(1,2,1);
b2=subplot(1,2,2);
for counter=1:2;
if counter==1
set(a1, 'Position', unitsPerInches); % affect only position of a1
end
subplot(1,2,counter);
imagesc(rand(3));
drawnow
subplot(1,2,counter);
imagesc(rand(3));
drawnow
end
Output: second figure of subplots fails.
System: Linux Ubuntu 16.04 64 bit
Linux kernel 4.6
Matlab: 2016a
Related threads: Matlab7 'bug' when using "subplot" + "imagesc"?
I'm not 100% sure what you're asking, but I think it's about combining multiple imagesc statements while in a loop. I'd do something more direct -- use gca and put the subplot inside the loop. Quite often, if you want to programmatically address multiple images, it makes sense to put them in some sort of structure other than creating lots of differently named variables. Note also that while 1 is probably not really what you want -- it will hammer your graphics device drivers -- and that pause can take an argument to act as a wait function, for some fraction of a second if required.
testImages{1}=double(imread('coins.png'));
testImages{2}=double(imread('cameraman.tif'));
h=figure;
set(h,'color','w'); %This handle refers to the background window
for ix=1:2
subplot(1,2,ix);
imagesc(testImages{ix});
axis equal;
colormap gray;
%Change, for example, axis position
curPoss=get(gca,'Position'); %gca stands for 'get current axis'
set(gca,'Position',curPoss+1e-2*ix^2); %Move one image up a bit
end
Does that help?
If you want to jump between figures, make an array of them, and use it within a loop:
unitsPerInches = [0.1 0.1 0.15 0.15];
figs = [figure(1) figure(2)];
for f = 1:numel(figs)
figure(figs(f));
for counter = 1:2;
subplot(1,2,counter);
imagesc(rand(3));
drawnow
end
figs(f).Children(1).Position = unitsPerInches;
figs(f).Children(2).Position = unitsPerInches+0.3;
end
Your original values for unitsPerInches was wrong, since the 'Position' property of an axes takes values between 0 to 1 by default. You can change this using the 'Units' property, like:
figs(f).Children(1).Units = 'inches';
The output from this example is two figures that looks like this:
Where there is a small axes on the down-left and a big one on the top-right.
So, back to your original questions:
What is imagesc corresponding structure to plot(a1,rand(3))?
Instead of passing the axes to imagesc, set the focus on the relevant figure, and subplot with:
figure(h)
subplot(x,y,c)
imagesc(data)
where h is a handle to the relevant figure, c is the place of the subplot within h where you want to plot the image (a number between 1 to x*y), and after these two line you call imagesc.
How to change 'Position' of figure inside the loop?
In this question it is not clear if you want to change the 'Position' of the figure or the axes, they have different units and meaning, but both are accessible in the same way:
h.Position = [left bottom width height]; % for the position of the figure
h.Children(c).Position = [left bottom width height]; % for the position of the axes
where h is as before, but c may be numbered differently, so subplot(x,y,c) may not refer to the same axes as h.Children(c). However, you can always use gca to get the current axes handle:
ax = gca;
ax.Position = [left bottom width height];
Hope it's all clear now, and if there are further questions, let me know ;)

Rotate MATLAB legend

Is there a way to rotate the MATLAB legend inside a plot? The image below should clarify my requirement.
the legend function can return serval of args:
[leg,labelhandles,outH,outM] = legend(varargin)
When you ask for the 2nd argument you get a list of all the Children and then you can use what phil's answer:
set(hc(3),'Position',[0.5 0.6 0],'Rotation',90); % Relocate and rotate text
set(hc(2),'Xdata',[0.5 0.5],'YData',[0.1 0.5]); % rotate the line
set(hc(1),'XData',0.5,'YData',0.3); % R
This is correct for matlab 2021b
You'll need to play around with the positioning, and need to do more work if you have more than one line plotted, but the following does it for your example.
plot(1:10); % create a dummy line
ha = legend('Plot'); %create a legend
set(ha,'Units','pixels'); % set axes unit to pixels
pos = get(ha,'Position'); % get the axes position
set(ha,'Position',[pos(1) pos(2)-pos(3) pos(4) pos(3)]); % Set the new position
hc = get(ha,'Children'); % Get the legend contents
set(hc(3),'Position',[0.5 0.6 0],'Rotation',90); % Relocate and rotate text
set(hc(2),'Xdata',[0.5 0.5],'YData',[0.1 0.5]); % rotate the line
set(hc(1),'XData',0.5,'YData',0.3); % Rotate the Marker
The example is not fully automated but should set you on the right route. You need to rotate the box containing the legend, and the label with the text./
% Example plot
plot(1:10)
h = legend('something')
% Rotate legend
set(h,'CameraUpVector', [1 0 0], 'Units','pixels','position',[460 230 25 150])
% Rotate text label
txt = findobj(h,'type','text');
set(txt,'rotation',90)
Unfortunately, the save as function restores the 'CameraUpVector'.

Moving MATLAB axis ticks by a half step

I'm trying to position MATLAB's ticks to line up with my grid, but I can't find a good way to offset the labels.
Also, if I run set(gca,'XTickLabel',1:10), my x tick labels end up ranging from 1 to 5. What gives?
You need to move the ticks, but get the labels before and write them back after moving:
f = figure(1)
X = randi(10,10,10);
surf(X)
view(0,90)
ax = gca;
XTick = get(ax, 'XTick')
XTickLabel = get(ax, 'XTickLabel')
set(ax,'XTick',XTick+0.5)
set(ax,'XTickLabel',XTickLabel)
YTick = get(ax, 'YTick')
YTickLabel = get(ax, 'YTickLabel')
set(ax,'YTick',YTick+0.5)
set(ax,'YTickLabel',YTickLabel)
Or if you know everything before, do it manually from the beginning:
[N,M] = size(X)
set(ax,'XTick',0.5+1:N)
set(ax,'XTickLabel',1:N)
set(ax,'YTick',0.5+1:M)
set(ax,'YTickLabel',1:M)
The marked answer works with a surf or mesh plot, however, I needed a solution which worked for a 2d plot.
This can be done by creating two axes, one to display the grid and the other to display the labels as follows
xlabels=1:1:10; %define where we want to see the labels
xgrid=0.5:1:10.5; %define where we want to see the grid
plot(xlabels,xlabels.^2); %plot a parabola as an example
set(gca,'xlim',[min(xgrid) max(xgrid)]); %set axis limits so we can see all the grid lines
set(gca,'XTickLabel',xlabels); %print the labels on this axis
axis2=copyobj(gca,gcf); %make an identical copy of the current axis and add it to the current figure
set(axis2,'Color','none'); %make the new axis transparent so we can see the plot
set(axis2,'xtick',xgrid,'XTickLabel',''); %set the tick marks to the grid, turning off labels
grid(axis2,'on'); %turn on the grid
This script displays the following figure :