How to make xTicks fit into all the plot window? - matlab

In the plot below how can I make the xTicks fit into all the x axis? I can not understand where the problem is and I will appreciate any advice as a new MATLAB user.
here is the part of code where I plot this graph :
f=figure();
plot(time, C, 'b*');
hold on
plot(time, L_Tilde, 'g-.');
plot(time, U_Tilde, 'g-.');
tickStep = 1 ;
tickDates = datenum( 1996:tickStep:2007 ,1,1) ;
set(gca, 'XTick' , tickDates , 'XTickLabel' , datestr(tickDates,'yyyy') )

Try
axis tight
This will will set the limits of both axes to exactly the limits of the data.

Just define the ylimit:
set(gca,'Xlim',[1996,2007])
set(gca, 'XTick' , tickDates , 'XTickLabel' , datestr(tickDates,'yyyy') )
Danny's suggestion is the automized way. To ge the 1996 back, you can add some days of margin to both sides:
%// example data
time = datenum( linspace(1996,2007),1,1);
L_Tilde = randi(10,[1,numel(time)]);
figure(1);
plot(time, L_Tilde, 'g-.');
tickStep = 1 ;
tickDates = datenum( 1996:tickStep:2007 ,1,1) ;
xlimms = get(gca,'Xlim');
axis tight
set(gca, 'XLim', get(gca,'XLim')+[-100,+100])
set(gca, 'XTick' , tickDates , 'XTickLabel' , datestr(tickDates,'yyyy') )
Adjust the 100 according to your needs.

Related

Matlab print -dpdf produces fuzzy lines

I have a problem when printing a 2D plot to pdf in matlab. I'm trying to print the following plot to a file (pdf, eps, svg, doesn't matter):
The problem is that at some points the line is very "jiggly" (sorry for the lack of a better word). I zoomed in on the upper part so you can see what I mean:
This is obviously not a problem for the matlab figure window. But when I print it to pdf, this is what it looks like:
The result is identical for pdf, svg and eps. I guess the problem is that matlab is creating a vectorized path (that is good!) but the path line is too thick and then every little spike can be seen.
Here's the code I'm using to produce the pdf:
sTitle = 'trajectory';
sFile = 'Data/trajectory.mat';
sPdfFile = 'pdfs/trajectory.pdf';
linewidth = 1;
fontsize1 = 18;
fig = figure;
% Adjust figure window size
set(fig, 'Position', [100 100 1400 800]);
% Set title
title(sTitle);
% Get states
[s, t] = load_data(some_data);
% Draw trajectory
plot(s(1,:), s(2,:), 'linewidth', linewidth);
% Labels and stuff
xlabel('x^W [m]', 'fontsize', fontsize1);
ylabel('y^W [m]', 'fontsize', fontsize1);
set(gca, 'fontsize', fontsize1)
% Axis font
set( gca , ...
'FontName' , 'Helvetica' );
set(gca, ...
'Box' , 'on' , ...
'TickDir' , 'out' , ...
'TickLength' , [.02 .02] , ...
'XMinorTick' , 'on' , ...
'XGrid' , 'on' , ...
'XMinorGrid' , 'off' , ...
'YMinorTick' , 'on' , ...
'YGrid' , 'on' , ...
'XColor' , [.3 .3 .3], ...
'YColor' , [.3 .3 .3], ...
'XTick' , -5:1:5, ...
'XTickLabelMode', 'auto', ...
'YTick' , -5:1:5, ...
'LineWidth' , 1 );
% Adjust view
axis([-2.5 2.5, -2.7 0.5]);
% Correct data aspect ratio
daspect([1,1,1])
% Print to PDF
width = 10;
height = 5;
set(gcf, 'PaperPosition', [0 0 width height]); %Position plot at left hand corner with width 5 and height 5.
set(gcf, 'PaperSize', [width height]); %Set the paper to have width 5 and height 5.
print('-dpdf', '-r600', sPdfFile);
According to this answer, this is an acknowledged bug, and the answerer provided a function to correct the issue for EPS files.
Since you are creating a PDF, I'd suggest using export_fig (requires a Ghostscript install) which, on the test script below, creates a smooth line in the produced PDF.
clc();
clear();
figure(1);
% Get states
n = 800;
x = linspace(0,2*pi,n);
s = [x.*cos(x);x.*sin(x)] + 0.3*exp(-0.3*[x;x]).*(rand(2,n)-0.5) ;
% Draw trajectory
plot(s(1,:), s(2,:), 'linewidth', 1);
axis([-20,20,-20,20]);
daspect([1,1,1])
% Print to PDF
print('traj.pdf','-dpdf', '-r600');
export_fig('traj2.pdf','-dpdf','-r600');
print PDF output:
export_fig PDF output:

How to change spectrogram's x-axis ticks?

Say, I have an example signal, which is a simple 1x1001 array. I had plotted it on the normal, line plot, beside of its spectrogram (see below). Now, as you can see, x-axis of the line plot is expressed in respect to the signal length. How can I share this x-axis with the spectrogram? Unfortunetaly, the solution proposed here: https://stackoverflow.com/questions/28676100/set-the-same-ticks-range-for-each-subplots-x-axis is not working, and the person, who gave me the answer advice me to create a new, specific topic.
Anyway, here is my code with working example:
t = 0:0.001:1; % time in milliseconds
f0 = 100;
f1 = 400;
signal = chirp(t, f0, 1, f1, 'q', [], 'convex');
frequencies = 0:.1:500;
window = 256;
NFFT = 255;
figure;
p1 = subplot(2, 1, 1);
spectrogram(signal, window, NFFT, frequencies, 1E3, 'yaxis');
axis xy; axis tight; colormap(jet); view(0,90);
xlabel('Time');
ylabel('Frequency (Hz)');
p2 = subplot(2, 1, 2);
plot(signal);
xlabel('Time (ms)');
ylabel('Amplitude (uV)');
The spectrogram's x-axis ticks should span from 0 to 1000.
Thank you in advance.
Here is a solution involving XTickLabel ( to insert after your first subplot):
Xlim = get(gca, 'xlim');
set(gca, 'XTick', linspace(Xlim(1), Xlim(2), 7);
set(gca, 'XTicklabel', 0:100:1200);
Best

matlab bar colormap returns the same color for all bars

I have a problem with using bar and colormap.
I have a csv file like this which contains completion time for six tasks:
34,22,103,22,171,26
24,20,41,28,78,28
37,19,60,23,141,24
...
and I create a bar chart with of the means, and add the std variation errorbar.
res = csvread('sorting_results.csv');
figure();
y = mean(res)';
e = std(res);
hold on;
bar(y);
errorbar(y,e,'.r');
title('Sorting completion time');
ylabel('Completion time (seconds)');
xlabel('Task No.');
hold off;
colormap(summer(size(y,2)));
Why is the output like this? Why do the bars have the same color? And how do I put legends to the six bars?
A piece of code that does the magic. It doesn't use the canonical technique mentioned by #am304, as you will have a hard time setting up the legend with it. Here, for each one of the 6 input values, we plot a full 6 bars: one bar with the value and the remaining five set to zero.
x = rand(1,6); %create data
x_diag = diag(x); %zero matrix with diagonal filled with x
cmap = summer(6); %define colors to use (summer colomap)
figure('color','w','Render','Zbuffer'); %create figure
%bar plot for each x value
for ind_data = 1:length(x)
h_bar = bar( x_diag(ind_data, :)); %bar plot
set( get(h_bar,'children'), 'FaceVertexCData', cmap(ind_data,:) ) ; %color
hold on;
end
colormap('summer');
%legend-type info
hleg = legend( ('a':'f')' );
set(hleg, 'box', 'off');
%xticks info
set(gca, 'XTickLabel', ('a':'f')' );
%plot errors
e = ones(1,6) * 0.05;
errorbar(x, e,'.r');
set(gca, 'FontSize', 14, 'YLim', [ 0 (max(x) + max(e) + 0.1) ]);
See Coloring 2-D Bars According to Height in the MATLAB documentation. Only the first colour of the colormap is used to colour the faces, you need a bit of hack (as per code on that doc page) to do what you want.

Distance between axis label and axis in MATLAB figure

I'm plotting some data with MATLAB and I'd like to adjust the distance between axis label and the axis itself. However, simply adding a bit to the "Position" property of the label makes the label move out of the figure window. Is there a "margin" property or something similar?
In the above figure, I'd like to increase the distance between the numbers and the label "Time (s)" while automatically extending the figures size so that the label does not move out of bounds.
This is how I set up the figure / axis.
figure;
set(gca, ...
'Box' , 'off' , ...
'LooseInset' , get(gca, 'TightInset') * 1.5 , ...
'TickDir' , 'in' , ...
'XMinorTick' , 'off' , ...
'YMinorTick' , 'off' , ...
'TickLength' , [.02 .02] , ...
'LineWidth' , 1 , ...
'XGrid' , 'off' , ...
'YGrid' , 'off' , ...
'FontSize' , 18 );
I wrote a function that should do exactly what you want. It keeps the axes at the exact same size and position, it moves the x-label down and increases the figure size to be large enough to show the label:
function moveLabel(ax,offset,hFig,hAxes)
% get figure position
posFig = get(hFig,'Position');
% get axes position in pixels
set(hAxes,'Units','pixels')
posAx = get(hAxes,'Position');
% get label position in pixels
if ax=='x'
set(get(hAxes,'XLabel'),'Units','pixels')
posLabel = get(get(hAxes,'XLabel'),'Position');
else
set(get(hAxes,'YLabel'),'Units','pixels')
posLabel = get(get(hAxes,'YLabel'),'Position');
end
% resize figure
if ax=='x'
posFigNew = posFig + [0 -offset 0 offset];
else
posFigNew = posFig + [-offset 0 offset 0];
end
set(hFig,'Position',posFigNew)
% move axes
if ax=='x'
set(hAxes,'Position',posAx+[0 offset 0 0])
else
set(hAxes,'Position',posAx+[offset 0 0 0])
end
% move label
if ax=='x'
set(get(hAxes,'XLabel'),'Position',posLabel+[0 -offset 0])
else
set(get(hAxes,'YLabel'),'Position',posLabel+[-offset 0 0])
end
% set units back to 'normalized' and 'data'
set(hAxes,'Units','normalized')
if ax=='x'
set(get(hAxes,'XLabel'),'Units','data')
else
set(get(hAxes,'YLabel'),'Units','data')
end
end
In this case offset should be the absolute offset in pixels. If you want relative offsets, I think this function could easily be rewritten. hFig is the figure handle and hAxes the axes handle.
EDIT: create the figure using hFig = figure; and the axes by hAxes = axes; (then set up the axes like you did in the question: set(hAxes,...)) before calling the function.
EDIT2: added the lines where the 'Units' of hAxes and the XLabel are changed back to 'normalized' and 'data' respectively. That way the figure stays the way you want it after resizing.
EDIT3: modified the function to work for both X and Y labels. Additional input ax should be 'x' or 'y'.
You can accomplish this by adjusting the position of the axis an xlabel. I also suggest using "normalized" units so your positioning does not depend on the data range. Here's an example:
figure
plot(rand(1,10))
set(gca, 'Units', 'Normalized');
pos = get(gca, 'Position');
offset = 0.1;
set(gca, ...
'Box' , 'off' , ...
'LooseInset' , get(gca, 'TightInset') * 1.5 , ...
'TickDir' , 'in' , ...
'XMinorTick' , 'off' , ...
'YMinorTick' , 'off' , ...
'TickLength' , [.02 .02] , ...
'LineWidth' , 1 , ...
'XGrid' , 'off' , ...
'YGrid' , 'off' , ...
'FontSize' , 18 , ...
'Position' , pos + [0, offset, 0, -offset]);
h = xlabel('Time (s)');
set(h, 'Units', 'Normalized');
pos = get(h, 'Position');
set(h, 'Position', pos + [0, -offset, 0]);
I know this has been answered and all, but this is (to some extent) a simpler way:
relative_offset = 1.5;
close all;
figure(99);clf
plot(rand(1,10))
xlabel('The x-axis')
xh = get(gca,'XLabel'); % Handle of the x label
pause(0.2)
set(xh, 'Units', 'Normalized')
pause(0.2)
pos = get(xh, 'Position');
set(xh, 'Position',pos.*[1,relative_offset,1])
I have included the pause commands, since my system will get ahead of itself in some weird way otherwise.
/Niels

Plot outside axis in Matlab

How to plot something outside the axis with MATLAB? I had like to plot something similar to this figure;
Thank you.
Here is one possible trick by using two axes:
%# plot data as usual
x = randn(1000,1);
[count bin] = hist(x,50);
figure, bar(bin,count,'hist')
hAx1 = gca;
%# create a second axis as copy of first (without its content),
%# reduce its size, and set limits accordingly
hAx2 = copyobj(hAx1,gcf);
set(hAx2, 'Position',get(hAx1,'Position').*[1 1 1 0.9], ...
'XLimMode','manual', 'YLimMode','manual', ...
'YLim',get(hAx1,'YLim').*[1 0.9])
delete(get(hAx2,'Children'))
%# hide first axis, and adjust Z-order
axis(hAx1,'off')
uistack(hAx1,'top')
%# add title and labels
title(hAx2,'Title')
xlabel(hAx2, 'Frequency'), ylabel(hAx2, 'Mag')
and here is the plot before and after:
You can display one axis with the scale you want, then plot your data on another axis which is invisible and large enough to hold the data you need:
f = figure;
% some fake data
x = 0:20;
y = 23-x;
a_max = 20;
b_max = 23;
a_height = .7;
%% axes you'll see
a = axes('Position', [.1 .1 .8 a_height]);
xlim([0 20]);
ylim([0 20]);
%% axes you'll use
scale = b_max/a_max;
a2 = axes('Position', [.1 .1 .8 scale*a_height]);
p = plot(x, y);
xlim([0 20]);
ylim([0 b_max]);
set(a2, 'Color', 'none', 'Visible', 'off');
I had similar problem and I've solved it thanks to this answer. In case of bar series the code is as follows:
[a,b] = hist(randn(1000,1)); % generate random data and histogram
h = bar(b,a); % plot bar series
ylim([0 70]) % set limits
set(get(h,'children'),'clipping','off')% turn off clippings