How to add a spanning ylabel on tiledlayout plots? - matlab

I've got a tiled layout in MATLAB with 3 tiles and I want to add a vertical label left to the y-axis, spanning over all tiles.
figure('units','normalized','outerposition',[0 0 0.4 0.91])
tlo = tiledlayout(3,1,'TileSpacing','none','Padding','none');
nexttile
set(gca,'XColor','none')
hold on
plot(x1)
hold off
nexttile
set(gca,'XColor','none')
hold on
plot(x2)
hold off
nexttile
hold on
plot(x3)
hold off

As the documentation on tiledlayout() tells you:
title(t,'Size vs. Distance')
xlabel(t,'Distance (mm)')
ylabel(t,'Size (mm)')
generates spanning axis labels and titles. In your case ylabel(tlo,'Your Y label');
Two style notes:
if you're only plotting a single plot, there's no need to hold on;hold off every plot. Also hold off is only necessary if at some point you no longer want to hold the plot, i.e. when you want to overwrite its contents.
set(gca, __) has been superseded by OOP style syntax. Using t1 = nexttile; t1.XColor = 'none' makes for cleaner and supposedly faster code.

Related

Two y-axis in Matlab: Setting different ranges and color

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]');

Remove border around axes but keep the grid and ticklabels [duplicate]

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);

Placing ticks in the middle of each grid in matlab

I am trying to create a figure with axes on matlab. But I want the ticks on the y-axis to be in the middle of each grid. How do I do that?
An example is like this:
As a workaround, you could turn on both major and minor gridlines, but set the major ones to the back color like this:
ax = axes;
grid(ax,'on');
grid(ax,'Minor');
set(ax,'GridColor',get(ax,'Color'))
set(ax,'MinorGridLineStyle','-')
set(ax,'TickLength',[0;0]);
Which gives:
I'm not aware of a specific matlab function to accomplish this.
As a solution, you can draw the grid yourself with vertical and horizontal lines at 0.5, 1.5, 2.5, ...
I have also found another way by drawing my own minor gridlines and not showing the major gridlines.
figure1 = figure;
axes1 = axes('Parent',figure1,'ZGrid','on','XGrid','on',...
'YTickLabel',{'','1','2','3', ''},...
'YTick',[0 1 2 3 4 ],...
'YGrid', 'off')
ylim([0.5 3.5]);
xlim([0 20]);
% gridlines ---------------------------
hold on
g_y=[0.5:1:4]; % user defined grid Y [start:spaces:end]
g_x=[0:2:20]; % user defined grid X [start:spaces:end]
for i=1:length(g_y)
plot([g_x(1) g_x(end)],[g_y(i) g_y(i)],'k-') %x grid lines
end
Output:
Credit goes to https://au.mathworks.com/matlabcentral/answers/95511-in-matlab-is-there-a-way-to-set-the-grid-at-a-spacing-different-from-the-ticks-on-the-axes

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 :

Plotting a subplot on top of another plot in Matlab

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?