I want to shift the x ticks labels downwards in this figure:
I'm not sure how to do this?
This is the script I'm using:
y=[0.5093 0.8526 0.9171];
x=[0 1600 1100];
hand =plot(y, 'ob-');
set(gca, 'XTick',1:3, 'XTickLabel',{'no interference' '1600' '1100'})
set(hand, 'LineWidth', 4);
set(hand, 'MarkerSize', 30);
set(findobj('type','text'),'FontSize',25);
set(gca,'FontSize',25);
set(findobj('type','axes'),'FontSize',25);
h=get(gca,'Title');
set(h,'FontSize',20);
Following the example from this mathworks solution, you can use the text function to add labels in any position you wish.
Increase the value of delta for a larger gap between x tick labels and x axis.
EDIT: Added custom control of yticks: the value of stp changes the step between each tick. Obviously a more general solution would identify the end-points of the tick range automatically as well.
figure(1), clf
% set data as your example
y=[0.5093 0.8526 0.9171];
x=[0 1600 1100];
Xt=1:length(x);
hand =plot(y, 'ob-');
set(gca, 'XTick',Xt);
stp=0.05;
Yt=0.5:stp:0.95;
set(gca, 'ytick', Yt)
% Reduce the size of the axis so that all the labels fit in the figure.
pos = get(gca,'Position');
set(gca,'Position',[pos(1), .2, pos(3) .7])
ax = axis; % Current axis limits
axis(axis); % Set the axis limit modes (e.g. XLimMode) to manual
Yl = ax(3:4); % Y-axis limits
Xl = ax(1:2);
% Place the text labels -- the value of delta modifies how far the labels
% are from the axis.
delta=0.1;
t = text(Xt, Yl(1)*ones(1,length(x))-delta, {'no interference' '1600' '1100'});
%set(t, 'HorizontalAlignment','left','VerticalAlignment','top')
set(t, 'HorizontalAlignment','center','VerticalAlignment','middle')
% Remove the default labels
set(gca,'XTickLabel','')
% and continue with your other settings as required
set(hand, 'LineWidth', 4);
set(hand, 'MarkerSize', 30);
set(findobj('type','text'),'FontSize',25);
set(gca,'FontSize',25);
set(findobj('type','axes'),'FontSize',25);
h=get(gca,'Title');
set(h,'FontSize',20);
The text function has lots of options that you can configure.
I think what most people want is something that works in 2-3 lines of code, nevermind-ing a quick&dirty approach.
This is undocumented (credits go to here) but just works:
% adjust ticklabels away from axes
a=gca;
a.XRuler.TickLabelGapOffset = 8;
a.YRuler.TickLabelGapOffset = 8;
tested with Matlab 2019a
Related
I am a noob when it comes to Matlab and I would appreciate any help! I need to create a figure with two y axis, and in order to satisfy my tutors I have to use specific ranges for them, and also to make it "more appealing" use colours that make some sense.
So I have two questions:
First, how can I set different ranges for the two y axis? I know I can use ylim([]} easily for 1 y axis but that doesn't seem to work.
Secondly, how can I easily change the color and format of one plot?(preferably they are the same as the color of the y axis they are assigned to, but Matlab automatically chooses them weirdly) Sadly sth like this won't work:
plot(x,y,'r','-','LineWidth',2.0);
It would be perfect if the first and second plot have the same format so '-' and the third and fourth another e.g. '--' but the plots Colors stay the same as their respective axis.
This is my current figure:
The following is my code
clc
A=dlmread('bipsim2_220.txt');
B=dlmread('bipsim2_680.txt');
x=A(:,1);
y=A(:,3);
plot(x,y,'LineWidth',2.0);
yyaxis left
hold on
x2=A(:,1);
y2=A(:,2);
plot(x2,y2,'LineWidth',2.0);
yyaxis right
hold on
x3=B(:,1);
y3=B(:,3);
plot(x3,y3,'LineWidth',2.0);
yyaxis left
hold on
x4=B(:,1);
y4=B(:,2);
plot(x4,y4,'LineWidth',2.0);
yyaxis right
yyaxis left
ylabel('Verstärkung (dB)')
yyaxis right
ylabel('Phase (deg)')
ylabel('Freq (Hz)')
set(gca,'Xscale','log')
set(gca,'fontsize',18)
hold off
grid minor
legend('R48/220 Ω: Phase [deg]','R48/220 Ω: Gain [dB]','R51/680 Ω: Phase [deg]','R51/680 Ω: Gain [dB]')
Thanks in advance for any help!
You can specify colors using RGB tuple with the color keyword agrument
You can specify linewidth using the linewidth keyword argument
You can specify styles as a positional argument after the data.
You can easily get X with logscale using semilogx
twinx will create a secondary Y-axis on with the labels on the right sharing the same X-axis.
import numpy as np
import matplotlib.pyplot as plt
freq = np.logspace(0, 5) # your frequency grid
# I made up a transfer function
H = lambda s: (s**2 - 1e2*s + 1e2) / (s - 1e3)**2
g = H(2j * np.pi * freq); # evaluate the transfer function at the frequency grid
# plot
plt.semilogx(freq, 20 * np.log10(abs(g)), '--k', linewidth=2)
plt.ylabel('Gain [dB]')
plt.xlabel('Frequency [Hz]');
plt.grid()
plt.twinx()
plt.semilogx(freq, 180 * np.angle(g) / np.pi, '-', linewidth=2, color=[0.8, 0.5, 0.3])
plt.ylabel('Phase [degrees]')
you can also specify predefined colors e.g k for black.
A few things to note:
You only need to call hold on once on the figure. Everything plotted after the first hold on will keep in the plot until you clear it with clf.
You can specify color and line style for each of your plots individually in its respective call to plot(...)
You need to set yyaxis left or yyaxis right before the thing you want to appear on that axis. This Matlab "from now on, we're now going to use the left/right axis"
On the same note, once you've set the approriate axis, you can manipulate its color and range.
In your code (untested because I don't have your input text files):
A=dlmread('bipsim2_220.txt');
B=dlmread('bipsim2_680.txt');
% resorted to have data and plotting separate (no need to do this, just easier to read the plotting part)
x1=A(:,1);
y1=A(:,3);
x2=A(:,1);
y2=A(:,2);
x3=B(:,1);
y3=B(:,3);
x4=B(:,1);
y4=B(:,2);
% set colors as a variables to change them easier
colorLeft = 'r'; % red
colorRight = 'k'; % black
% let's just open a clean figure
clf;
% set hold to on
hold on;
%% do stuff for the left y axis (gain)
yyaxis left;
% plot data with respective color and line style
plot(x1,y1,'LineWidth',2.0, 'Color', colorLeft, 'LineStyle', '-');
plot(x3,y3,'LineWidth',2.0, 'Color', colorLeft, 'LineStyle', '--');
% axis formating
ylabel('Verstärkung (dB)');
ylim([-200, 50]); % chose lower and upper limit for left y-axis
ax = gca; % all the formating of the axis is stored in an axis object which we can manipulate
ax.YColor = colorLeft; % set color of current (i.e. left) y-axis
%% now we move to do stuff for the right y axis (phase)
yyaxis right;
% plot data with respective color and line style
plot(x2,y2,'LineWidth',2.0, 'Color', colorRight, 'LineStyle', '-');
plot(x4,y4,'LineWidth',2.0, 'Color', colorRight, 'LineStyle', '--');
% axis formating
ylabel('Phase (deg)');
ylim([-180, 0]); % chose lower and upper limit for right y-axis
ax.YColor = colorRight; % set color of current (i.e. right) y-axis
%% finally, set all the format stuff not related to a particular y-axis
xlabel('Freq (Hz)')
ax.XScale = 'log';
ax.FontSize = 18;
grid minor
% hold off % no need to turn hold off, its only affecting the current figure anyway
%make sure that the order of legend entries fits the order in which you plot the curves
legend('R48/220 Ω: Gain [dB]','R51/680 Ω: Gain [dB]', 'R48/220 Ω: Phase [deg]','R51/680 Ω: Phase [deg]');
Is there a way to remove only the axis lines in the Matlab figure, without affecting ticks and tick labels.
I know that box toggles the upper and right axes lines and ticks and that works perfectly for me.
But my problem is that I want eliminate the bottom and left lines (only lines!) but keeping the ticks and tick labels.
Any tricks?
Yair Altman's Undocumented Matlab demonstrates a cleaner way to do this using the undocumented axes rulers:
plot(x,y);
ax1 = gca;
yruler = ax1.YRuler;
yruler.Axle.Visible = 'off';
xruler = ax1.XRuler;
xruler.Axle.Visible = 'off'; %// note you can do different formatting too such as xruler.Axle.LineWidth = 1.5;
A nice feature of this approach is that you can separately format the x and y axis lines.
Solution for Matlab versions prior to R2014b
You can introduce a new white bounding box and put it on top.
// example data
x = linspace(-4,4,100);
y = 16 - x.^2;
plot(x,y); hold on
ax1 = gca;
set(ax1,'box','off') %// here you can basically decide whether you like ticks on
%// top and on the right side or not
%// new white bounding box on top
ax2 = axes('Position', get(ax1, 'Position'),'Color','none');
set(ax2,'XTick',[],'YTick',[],'XColor','w','YColor','w','box','on','layer','top')
%// you can plot more afterwards and it doesn't effect the white box.
plot(ax1,x,-y); hold on
ylim(ax1,[-30,30])
Important is to deactivate the ticks of the second axes, to keep the ticks of the f rist one.
In Luis Mendo's solution, the plotted lines are fixed and stay at their initial position if you change the axes properties afterwards. That won't happen here, they get adjusted to the new limits. Use the correct handle for every command and there won't be much problems.
Dan's solution is easier, but does not apply for Matlab versions before R2014b.
There is another undocumented way (applicable to MATLAB R2014b and later versions) of removing the lines by changing the 'LineStyle' of rulers to 'none'.
Example:
figure;
plot(1:4,'o-'); %Plotting some data
pause(0.1); %Just to make sure that the plot is made before the next step
hAxes = gca; %Axis handle
%Changing 'LineStyle' to 'none'
hAxes.XRuler.Axle.LineStyle = 'none';
hAxes.YRuler.Axle.LineStyle = 'none';
%Default 'LineStyle': 'solid', Other possibilities: 'dashed', 'dotted', 'dashdot'
This is different from Dan's answer which uses the 'visible' property of rulers.
You could "erase" the axis lines by plotting a white line over them:
plot(1:4,1:4) %// example plot
box off %// remove outer border
hold on
a = axis; %// get axis size
plot([a(1) a(2)],[a(3) a(3)],'w'); %// plot white line over x axis
plot([a(1) a(1)],[a(3) a(4)],'w'); %// plot white line over y axis
Result:
As noted by #SardarUsama, in recent Matlab versions you may need to adjust the line width to cover the axes:
plot(1:4,1:4) %// example plot
box off %// remove outer border
hold on
a = axis; %// get axis size
plot([a(1) a(2)],[a(3) a(3)],'w', 'linewidth', 1.5); %// plot white line over x axis.
%// Set width manually
plot([a(1) a(1)],[a(3) a(4)],'w', 'linewidth', 1.5);
I would like create a Matlab figure with a double X axis (m/s and km/h) with the same plot.
I have found plotyy and - in Matlab reposity - plotyyy, but I am looking for:
A double X axis.
Together below the plot.
My code is very simple:
stem(M(:, 1) .* 3.6, M(:, 3));
grid on
xlabel('Speed (km/h)');
ylabel('Samples');
M(:, 1) is the speed (in m/s), and M(:, 3) is the data.
I would like only a second line, in the bottom, with the speeds in m/s.
You can do something like the following. In comparison to the solution of #Benoit_11 I do use the normal Matlab labels and refer to both axes with handles so the assignments are explicit.
The following code creates an empty x-axis b with the units m/s with a negligible height. After this, the actual plot is drawn in a second axes a located a bit above the other axes and with units km/h. To plot on a specific axes, insert the axes-handle as the first argument of stem. The conversion from m/s to km/h is directly written in the call to stem. Finally, it's needed to set the xlim-property of the both axes to the same values.
% experimental data
M(:,1) = [ 0, 1, 2, 3, 4, 5];
M(:,3) = [12, 10, 15, 12, 11, 13];
% get bounds
xmaxa = max(M(:,1))*3.6; % km/h
xmaxb = max(M(:,1)); % m/s
figure;
% axis for m/s
b=axes('Position',[.1 .1 .8 1e-12]);
set(b,'Units','normalized');
set(b,'Color','none');
% axis for km/h with stem-plot
a=axes('Position',[.1 .2 .8 .7]);
set(a,'Units','normalized');
stem(a,M(:,1).*3.6, M(:,3));
% set limits and labels
set(a,'xlim',[0 xmaxa]);
set(b,'xlim',[0 xmaxb]);
xlabel(a,'Speed (km/h)')
xlabel(b,'Speed (m/s)')
ylabel(a,'Samples');
title(a,'Double x-axis plot');
As a very simple alternative you could also create a 2nd axis (transparent) and put it below the first one so that you only see the x axis.
Example:
clear
clc
close all
x = 1:10;
x2 = x/3.6;
y = rand(size(x));
hP1 = plot(x,y);
a1Pos = get(gca,'Position');
%// Place axis 2 below the 1st.
ax2 = axes('Position',[a1Pos(1) a1Pos(2)-.05 a1Pos(3) a1Pos(4)],'Color','none','YTick',[],'YTickLabel',[]);
%// Adjust limits
xlim([min(x2(:)) max(x2(:))])
text(2.85,0 ,'m/s','FontSize',14,'Color','r')
text(2.85,.05 ,'km/h','FontSize',14,'Color','r')
Output:
Then you can manually add the x labels for each unit, in different color for example.
The best way i can think to do it is to use 2 plots, for example, you can split the plot into a large and small section by doing something like this:
subplot(100, 1, 1:99) // plot your graph as you normally would
plot(...
subplot(100, 1, 100) // Plot a really small plot to get the axis
plot(...)
b = axis()
axis([b(1:2), 0, 0]) // set the y axis to really small
This is untested, you might need to fiddle around a little but it should hopefully put you on the right track.
I have some points in a 'jet' colormap. The points have a coefficient that can go from 0 to 1, but usually they dont cover all the range, e.g 0.75-0.9.
When I plot those points I colour them so 0.75 is the lesser colour in the colormap and 0.9 is the maximum color in the colormap, so all the colormap is shown. What I want to do is show that in the colorbar also. When I plot the colorbar the labels on it go to 64, but I want them from 0.75 to 0.9. How can I do that?
EDIT
I don't think the code itself helps a lot but here it goes, just in case. In the colors variable I convert the ZNCC to the range of the colormap.
EDIT2
I found the reason why caxis is not working for me. Here is the code:
%this is why it doesnt work
im=imread('someimageyouwanttotest_inRGB.png')
imshow(im)
points=[1, 2;1 , 2 ;0.3,0.7]
ZNCC=points(3,:)
cmap=colormap('jet');
colors=cmap(round( ((1-min(ZNCC))+ZNCC-1).*(size(cmap,1)-1)/max((1-min(ZNCC))+ZNCC-1))+1,: );
hold on
for i=1:length(ZNCC)
plot(points(1,i),points(2,i),'.','Color',colors(i,:));
end
colorbar()
hold off
I think that is your code displays all your colours correctly then rather just set up the colour bar first on no image:
points=[1, 2;1 , 2 ;0.3,0.7]
ZNCC=points(3,:)
cmap=colormap('jet');
caxis([min(ZNCC) max(ZNCC)]);
colorbar();
hold on
%this is why it doesnt work
im=imread('someimageyouwanttotest_inRGB.png')
imshow(im)
colors=cmap(round( ((1-min(ZNCC))+ZNCC-1).*(size(cmap,1)-1)/max((1-min(ZNCC))+ZNCC-1))+1,: );
for i=1:length(ZNCC)
plot(points(1,i),points(2,i),'.','Color',colors(i,:));
end
hold off
I can't test it as I don't have imshow :/
If caxis is not working for you, you could store the return from colorbar - it is a handle to the colorbar object. Then you can set its properties, like 'YTick' and 'YLim'. The full list of properties you can set is the same as the Axes Properties (because the colorbar is just an axes object, after all).
Here is an example:
% Generate some random data
z = rand(10);
[x, y] = meshgrid(1:size(z, 1));
% Plot colour map
pcolor(x, y, z);
shading interp; % Comment out to disable colour interpolation
colormap jet;
% Setup colorbar
c = colorbar();
set(c, 'YTick', [0.75 0.875 1]); % In this example, just use three ticks for illustation
ylim(c, [0.75 1]);
It is only necessary to do this once, after you've finished plotting.
Edit: If you need the limits and ticks automatically from the data, then you can do something like
% Find the limits
lims = [min(z(:)) max(z(:))];
% Function for rounding to specified decimal places
dprnd = #(x, dps)round(x*(10.^dps))./(10.^dps);
% Generate ticks
nTicks = 5;
nDps = 2;
ticks = dprnd(linspace(lims(1), lims(2), nTicks), nDps);
set(c, 'YTick', ticks);
I need to plot several plots along a sloped line at different positions.
For example, if I:
plot(0:200,'k');
plotpts = 5:5:200;
I would like to be able to plot a smaller plot at each of my plotpts on top of the original 0:200 line.
I know you can use hold on and plot over top that way, but I need to change my origin each time. Does anyone have any suggestions? I would really like to stay in matlab. Thanks!
Here is a flexible way I usually do it:
plot(1:10, 'k')
plotpts = 2:2:8;
mainbox = get(gca, 'Position');
xlims = get(gca, 'XLim');
ylims = get(gca, 'Ylim');
for i=1:length(plotpts)
originx = mainbox(1) + (plotpts(i) - xlims(1)) * (mainbox(3)) / (xlims(2) - xlims(1));
originy = mainbox(2) + (plotpts(i) - ylims(1)) * (mainbox(4)) / (ylims(2) - ylims(1));
axes('position', [originx originy 0.1 0.1], 'Color', 'none')
% Do some plotting here...
end
It's quite a bit of work, but you probably want to use the axes command. A figure window can host any number of axes, where each axes has it's own position, data, annotations, color etc.
The most difficult thing for the application you describe is that each axis position needs to be defined in the coordinate frame of the underlying figure, which means that some math may be required to create the illusion that the axis is correctly positioned within a parent axes/
For example, if you first create a simple plot
figure(1234); clf;
plot(1:10, rand(1,10),'.k-','linewidth',5);
xlim([1 10]);
ylim([0 1]);
set(gca,'color','y'); %This just helps demonstrate the next steps
You can place another axis directly on top of the first, and then
ha = axes('position',[.2 .3 .1 .1])
plot(linspace(0,2*pi,100), sin(linspace(0,2*pi,100)), 'b-')
xlim([0 2*pi])
You can adjust the the properties of the inset axis to suit your particular needs, for example
set(ha,'color','none'); %A transparent axis
set(ha,'xtick',[],'ytick',[]); %Remove tick labels
title(ha,'This is an inset plot')
Is the command subplot not what you're looking for?