Multiple x-axis and y-axis with plots in MATLAB - matlab

I am trying to follow MATLAB's documentation here Graph with Multiple x-axes and y-axes to plot with 2 x and y-axes, but instead with plots rather than lines. This is what I have so far:
clear all; close all; clc;
% Arbitrary x's and y's
x1 = [10 20 30 40];
y1 = [1 2 3 4];
x2 = [100 200 300 400];
y2 = [105 95 85 75];
figure
plot(x1,y1,'Color','r')
ax1 = gca; % current axes
ax1.XColor = 'r';
ax1.YColor = 'r';
ax1_pos = ax1.Position; % position of first axes
ax2 = axes('Position',ax1_pos,...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none');
%line(x2,y2,'Parent',ax2,'Color','k') <--- This line works
plot(ax2, x2, y2) <--- This line doesn't work
I've looked the plot documentation 2-D line plot but cannot seem to get plot(ax,__) to help/do what I expect.
The figure ends up not plotting the second plot and the axes end up overlapping.
Any suggestions how to fix this and get 2 axes plotting to work?
I'm currently using MATLAB R2014b.

Finally figured this one out after trying to think about MATLAB's hierarchy of setting things.
The plot seems to reset the axis ax2 properties so setting them before plot doesn't make a difference. line doesn't do this it seems. So to get this to work with plots I did the following:
clear all; close all; clc;
% Arbitrary x's and y's
x1 = [10 20 30 40];
y1 = [1 2 3 4];
x2 = [100 200 300 400];
y2 = [105 95 85 75];
figure
plot(x1,y1,'o', 'MarkerEdgeColor', 'r', 'MarkerFaceColor', 'r')
ax2 = axes('Color','none'); % Create secondary axis
plot(ax2, x2,y2,'o', 'MarkerEdgeColor', 'b', 'MarkerFaceColor', 'b')
% Now set the secondary axis attributes
ax2.Color = 'none'; % Make the chart area transparent
ax2.XAxisLocation = 'top'; % Move the secondary x axis to the top
ax2.YAxisLocation = 'right'; % Move the secondary y axis to the right

Related

Correctly aligning labels for subgroups within a tiledlayout

I want to put 5 plots in a figure using tiledlayout, 2x2 plots at the top then a plot at the bottom that spans two columns. There should be two sets of axis labels: one for the 2x2 plot and another for the bottom plot. My MWE is
x = linspace(-2,2,100);
y1 = sin(x);
y2 = cos(x);
y3 = sin(x).*cos(2*x);
y4 = sin(2*x).*cos(x);
y5 = y3 + y4;
figure('PaperUnits', 'inches', 'PaperSize', [4 6], 'PaperPosition', [0 0 4 6]);
t = tiledlayout(3,2,'TileSpacing','compact','Padding','compact');
nexttile; plot(x,y1); title('y_1');
nexttile; plot(x,y2); title('y_2');
nexttile; plot(x,y3); title('y_3');
nexttile; plot(x,y4); title('y_4');
xlabel(t,'time t_\alpha')
ylabel(t,'amplitude \alpha')
nexttile([1 2]); plot(x,y5); title('y_5');
xlabel('time t_\beta')
ylabel('amplitude \beta')
saveas(gcf,'myfig.jpg')
This gives me the following figure:
I want the amplitude \alpha ylabel and the time t_alpha xlabel to be aligned correctly for the 2x2 plots (as indicated by my red annotations). Is there a way to do this?
I'm using MATLAB R2020a. Note that the tiledlayout function was introduced in R2019b.
An approximation of what you wanted can be achieved by the approach I mentioned in my comment (using a "nested" tiledlayout). The steps necessary to make it work are:
Creating an external vertical layout.
Reserving the first two rows for the nested tiledlayout, by asking a 2-by-1 nexttile, making the resulting axes hidden, and creating a uipanel in its place. Calling uipanel is necessary because the parent of a tiledlayout cannot be another tiledlayout, but it can be a Panel.
Plotting everything in the appropriate panels, and applying the labels accordingly.
x = linspace(-2,2,100);
y1 = sin(x);
y2 = cos(x);
y3 = sin(x).*cos(2*x);
y4 = sin(2*x).*cos(x);
y5 = y3 + y4;
hF = figure('PaperUnits', 'inches', 'PaperSize', [4 6], 'PaperPosition', [0 0 4 6]);
tOut = tiledlayout(hF,3,1);
hAx = nexttile(tOut, [2,1]); hAx.Visible = 'off';
hP = uipanel(hF, 'Position', hAx.OuterPosition, 'BorderWidth', 0);
tIn = tiledlayout(hP,2,2,'TileSpacing','compact','Padding','compact');
nexttile(tIn); plot(x,y1); title('y_1');
nexttile(tIn); plot(x,y2); title('y_2');
nexttile(tIn); plot(x,y3); title('y_3');
nexttile(tIn); plot(x,y4); title('y_4');
xlabel(tIn,'time t_\alpha')
ylabel(tIn,'amplitude \alpha')
hAx = nexttile(tOut); plot(x,y5); title('y_5');
xlabel(hAx, 'time t_\beta')
ylabel(hAx, 'amplitude \beta')
Resulting in:
From here you can try tweaking the individual GUI elements (layouts, axes, panel) to get a result closer to what you wanted.
A completely different route I can suggest is starting with your code and adding the labels for the top 4 plots using the annotation function (instead of xlabel and ylabel).

How to smooth the edges in my contour plot corresponding to nan

This is the link to the dataset. I have this contour plot which has a bit rough edges. My question is, how can I smooth these edges these edges correspond to Nan. I filled in the Z matrix with Nan so as to remove unwanted values.
I also wanted to ask that why shading flat and interp is not working on this contour.
I have set shading to flat and in Matlab2013b I get proper flat figure but in Matlab 2014b and 2015b I am getting this figure.
MATLAB 2015b:
MATLAB 2013b
How can I obtain perfectly meshed plot in Matlab 2015b, I checked for shading options in the documentation and there are only 3 faceted, interp and flat.
shading flat works in 2013b but not in subsequent versions. Can someone tell me why is it so?
This is the sample code which I am using right now:
clear all; close all; clc;
load temperature.txt;
time = temperature(:,1); % This column contains the time
x = temperature(:,2); % This column contains the x values.
temperature_system = temperature(:,3); % This column contains the temperatures.
% Rejecting the outliers
pos = (temperature_system > prctile(temperature_system,97));
time(pos) = [];
x(pos) = [];
temperature_system(pos) = [];
X1 = [time x];
F = scatteredInterpolant(X1,temperature_system);
x1 = linspace(min(x),max(x),100);
x2 = linspace(min(time),max(time),100);
[X,Y] = meshgrid(x2,x1);
Z = F(X,Y);
% Is the data below the criteria for all points in space at a specific time
emptyTime = all(Z<10,1);
emptySpace = all(Z<10,2);
[emptyTime, emptySpace] = meshgrid(emptyTime, emptySpace);
Z(emptyTime | emptySpace) = nan;
% Replacing the remaining zeros with nan
pos = find(Z<1);
Z(pos) = nan;
f1 = figure(1);
%set(f1,'renderer','zbuffer');
%surf(X,Y,Z);
[C,h] = contourf(X,Y,Z, 'Linestyle', 'none');
shading flat;
colormap(jet);
q = colorbar;
set(q,'direction','reverse');
q.Label.String = 'Temperature';
xlabel('Time (ps)','FontSize', 16, 'FontWeight', 'bold',...
'FontName', 'Helvetica', 'Color', 'Black');
ylabel('Length of box (A)','FontSize', 16, 'FontWeight', 'bold',...
'FontName', 'Helvetica', 'Color', 'Black');
set(gca,'LineWidth',3,'TickLength',[0.02 0.02]);
set(gca,'XMinorTick','on');
set(gca,'YMinorTick','on','XTicksBetween', 5);
set(gca,'FontSize',12,'FontName','Helvetica');
It's difficult to test the issue without having your data. I got rid of the lines by means of the LineStyle property:
Code:
Z = peaks(20);
subplot(2,1,1);
contourf(Z,10);
colorbar;
subplot(2,1,2);
contourf(Z,10, 'LineStyle', 'none');
colorbar;

Zoom region within a plot in Matlab

I'm using Matlab to produce figures, and I'm wondering if there is a way to plot a zoomed region in a figure of the overall data?
I have scatter data plotted over one week, with the x-axis in hours, and I want to zoom into the first 3 hours, and display them within the main figure with the x-axis label of minutes.
The plotting code I have so far is as follows:
allvalsx = marabint(:,2)
allvalsy = marabint(:,5)
subvalsx = marabint(1:7,2);
subvalsy = marabint(1:7,2);
%% Plots the scatter chart.
sizemarker = 135
handle = scatter(allvalsx, allvalsy, sizemarker, '.')
figure(1)
axes('Position',[.2 .2 .2 .2])
handle2 = scatter(subvalsx, subvalsy, '.r')
title(plotTitle)
xlabel('Time since treatment (hours)')
ylabel('Contact angle (deg)')
% Axis scales x1, x2, y1, y2
axis([0, marabint(length(marabint),2) + 10, 0, 120]);
% This adds a red horizontal line indicating the untreated angle of the
% sample.
untreatedLine = line('XData', [0 marabint(length(marabint),2) + 10], 'YData', [untreatedAngle untreatedAngle], 'LineStyle', '-', ...
'LineWidth', 1, 'Color','r');
% Adding a legend to the graph
legendInfo = horzcat('Untreated angle of ', untreatedString)
hleg1 = legend(untreatedLine, legendInfo);
% This encases the plot in a box
a = gca;
% set box property to off and remove background color
set(a,'box','off','color','none')
% create new, empty axes with box but without ticks
b = axes('Position',get(a,'Position'),'box','on','xtick',[],'ytick',[]);
% set original axes as active
axes(a)
% link axes in case of zooming
linkaxes([a b])
set(gcf,'PaperUnits','inches');
set(gcf,'PaperSize', [8.267 5.25]);
set(gcf,'PaperPosition',[0 0.2625 8.267 4.75]);
set(gcf,'PaperPositionMode','Manual');
set(handle,'Marker','.');
print(gcf, '-dpdf', '-r150', horzcat('markertest4.pdf'));
This produces the following
Can anyone help me out with this?
yeah, I think I know what you need. Try this:
zoomStart = 0;
zoomStop = 3;
set(gca, 'XLim', [zoomStart zoomStop])
Let me know if that doesn't do what you need, and I'll give you a different way.

Large composed plots in a single subplot in Matlab

Introduction
I am currently working on a MATLAB script which handles a large plot rutine. In short I am creating a plot that consist of several other plots. Now I want this plot into a subplot with another plot. However, I cannot seem to get this working.
Code:
My first plot:
h = figure('Units', 'pixels', ...
'Position', [100 100 1000 375]);
= fill([xfit fliplr(xfit)],[meanSeq-stdSeq fliplr(meanSeq+stdSeq)],[0.7 0.7
0.7],'linestyle','none');
b = fill([xfit fliplr(xfit)],[meanMul-stdMul fliplr(meanMul+stdMul)],[0.7 0.7 0.7],'linestyle','none');
c = plot(xfit,meanSeq,'black','linewidth',1.5); %% change color or linewidth to adjust mean line
e = plot(xfit,meanSeq./7.5,'color',[0.75 0 0],'linewidth',1.5);
d = plot(xfit,meanMul,'b','linewidth',1.5); %% change color or linewidth to adjust mean line
axis([0 max(xfit) 0 max(meanSeq)+10]);
subplot(2,1,1);
and my second plot:
hTwo = figure('Units', 'pixels', ...
'Position', [100 100 1000 375]);
f = plot(xfit,meanSeq./meanMul,'linewidth',1.5);
hold on
g = plot(xfit,1/(0.01+0.99/8),'linewidth',1.5);
hij = plot(xfit,mean(meanSeq./meanMul),'linewidth',1.5);
axis([0 max(xfit) 5 8]);
subplot(2,1,2);
Question
Now, apperantly it is not possible to put these two separte plots into one subplot all I get is an empty white graph. Each plot rutine works seperatly.
You have to call the subplot(2,1,1) before you plot with plot().
As I'm not able to run your code I give you the general plan:
1- figure()
2- subplot(2,1,1)
3- plot() % plot data into first subplot
4- subplot(2,1,2)
5- plot() % plot data into second subplot

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