Interpolation Errors, plot function does not generate proper lines when running - matlab

I am trying to get a graph made for my interpolation program (basically it takes a test function and creates lines utilizing an interpolation method)
clear all;
close all;
clc;
x1= [-1 0.75 -0.5 -0.25 0 0.25 0.5 0.75 1];
x2=-1:1001:1;
y1=1./(1+25.*x1.^2);
y2=1./(1+25.*x2.^2);
figure(777)
title('Figure 777')
for loop=1:1:6
subplot(6,2,loop);
plot(x2,y2,'linewidth',2);
hold on
plot(x1,y1,'r.','markersize',25);
hold on
end
%%%(A)
[p1,s1,u1] = polyfit(x1,y1,4);
Y1=polyval(p1, x2, s1, u1);
subplot (6,2,1)
plot(x2,Y1,'b','linewidth',6);
%%%(B)
[p2, s2, u2] = polyfit(x1,y1,8);
Y2 = polyval(p2, x2, s2, u2);
subplot(6,2,1)
plot(x2,Y2, 'b', 'linewidth', 6);
%%%(C)
Y3 = interp1(x1, y1, x2, 'linear');
subplot(6,3,1)
plot(x2, Y3, 'b', 'linewidth', 6);
%%%(D)
Y4 = interp1(x1,y1,x2, 'nearest');
subplot(6,4,1)
plot(x2, Y4, 'b', 'linewidth', 6);
%%%(E)
Y5 = interp1(x1,y1,x2, 'spline');
subplot(6,5,1)
plot(x2, Y5, 'b', 'linewidth', 6);
%%%(F)%%%(This method does not exist for Matlab R2017a)
Y6 = interp1(x1,y1,x2, 'makima');
subplot(6,6,1)
plot(x2, Y6, 'b', 'linewidth', 6);
However, none of the lines appear when I run the program. Only the dots. Furthermore I receive these errors:
Warning: Polynomial is badly conditioned. Add points with distinct X values or
reduce the degree of the polynomial.
In polyfit (line 73)
In HwSixTwo (line 27)
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
F = griddedInterpolant(X,V,method);
Error in HwSixTwo (line 33)
Y3 = interp1(x1, y1, x2, 'linear');

Well one bug that would certainly not generate intended results is here:
x2=-1:1001:1;
I'm assuming it's your intent to create 1001 points evenly spaced between -1 to 1. This code is not doing this. The middle number specifies what the spacing is in between successive numbers. 1001 does not make sense which generates only one value which is -1.
Replace your code with the linspace function:
x2 = linspace(-1, 1, 1001);
Also, you're missing a minus sign in one of your values in x1 - the 0.75:
x1= [-1 -0.75 -0.5 -0.25 0 0.25 0.5 0.75 1];
% ^^^
As Cris noted, your x values must be monotonic or increasing / decreasing in one direction.

Related

How to set background in multiple colors in semilogy plot (MATLAB) ?

I am looking for a way to shade the background of my semilog plot in two colors.
For example, in the following image, I have am plotting three polynomials and they all are equal at x=1. I want one rectangle for x<1 region and other for x>1 region. How can I insert two such rectangles, of different colors, in background to highlight these two regions.
MWE:
x = 0.1:0.1:10;
y1 = polyval([1, 0], x); % Evaluate y = x;
y2 = polyval([1, 0, 0], x); % Evaluate y = x^2;
y3 = polyval([1, 0, 0, 0], x); % Evaluate y = x^3;
figure
semilogy(x, y1, '.k', x, y2, '.b', x, y3, '.r'); title ('Three
polynomials on a semilog y scale') xlabel('x'); ylabel('y');
legend({'y= x', 'y = x^2', 'y = x^3'}, 'Location', 'Northwest')
You can solve that using area or patch.
As pointed by #SardarUsama, there are others questions with good examples on it, however, you need to avoid to have any zeros in the area data, otherwise it will fail.
Follows the code setting one area only.
x = 0.1:0.1:10;
y1 = polyval([1, 0], x); % Evaluate y = x;
y2 = polyval([1, 0, 0], x); % Evaluate y = x^2;
y3 = polyval([1, 0, 0, 0], x); % Evaluate y = x^3;
figure
plot(x, y1, '.k', x, y2, '.b', x, y3, '.r'); %MODIFIED
hold on %ADDED
title ('Three polynomials on a semilog y scale')
set (gca, 'Yscale', 'log'); %ADDED
xlabel('x');
ylabel('y');
legend({'y= x', 'y = x^2', 'y = x^3'}, 'Location', 'Northwest')
area( [1 1 10 10],[1e-3 1e+3 1e+3 1e-3 ],'FaceColor','green','facealpha',0.3) %ADDED
The code above works for matlab after 2014b. If you have one before that, you can use the patch function (which requires some small change in the data, but uses the Facealpha option) or you can move the area to the background as i do below:
ax=get(gca,'Children'); %ADDED
set(gca,'Children',[ax(2) ax(3) ax(4) ax(1)]); %ADDED, move area to background
Note: Indeed, I missed the problem with the legend. I correct as mentioned, however for me the area was on top of the other graphs. To solve it i changed the order of the plots. If the area was with transparency, this will not be an issue.

Matlab : Can Conditional plotting done in a loop be vectorized?

I am wanting to do conditional plotting of vertical lines, that change color based on the value of an integer vector. Those values are integers that range from 0-4.
Currently, I am using a loop to go through the tables to plot the lines. This works, but for LARGE amounts of data it takes time, and I'm wondering if it can be vectorized.
Attached is a stripped down version of the script to loop through a data vector(sample) that simply Loops through the vector, and plots a vertical line based on the value of the integer.
I will also attach the simple variable I created called 'SAMPLE' below to paste into your workspace.
for i=1:size(sample,1)
if sample(i)==1
line( [i i] ,[0 10], 'Marker','.','LineStyle','-','Color','r');
elseif sample(i)==2
line( [i i] ,[0 10], 'Marker','.','LineStyle','-','Color','b');
elseif sample(i)==3
line( [i i] ,[0 10], 'Marker','.','LineStyle','-','Color',[1 .5 0]);
elseif sample(i)==4
line( [i i] ,[0 10], 'Marker','.','LineStyle','-','Color','g');
end
end
Variable:
sample=[[3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0]];
But is is possible to 'vectorize' plotting in this way w/o having to do it iteratively in a loop as I have done?
Take advantage of the fact that when plotting a line, MATLAB will skip points whose value is NaN.
% Your vector
sample=[3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0];
% Your colors
colors = [
1 0 0
0 0 1
1 .5 0
0 1 0];
for idx = 1:4
% Find the index of each of your integers
X = find(sample == (idx));
% Force X to be a row vector
X = X(:)';
% Stack two X's on top of one another with a third row filled
% with NaNs. Fill in your Y values in the same way while
% you're at it.
Y = [zeros(size(X)); 10 + zeros(size(X)); nan(size(X))];
X = [X; X; nan(size(X))]; %#ok<AGROW>
% Matlab is column major. By using the colon here, you
% produce a vector that is [X1 X1 nan X2 X2 nan ... etc.]
X = X(:);
Y = Y(:);
% Draw the line
line(X, Y, 'Marker', '.', 'LineStyle', '-', 'Color', colors(idx, :))
end
There's still a loop, but now you're just looping over the possible values instead of looping over the each value in the vector. I think you will find that this will scale much better.
Changing input to:
sample = zeros(1, 1e6);
for idx = 1:4
sample(randi(1e6, 1, 1000)) = idx;
end
and benchmarking with timeit gives a time of 0.0065706 seconds on my machine, while the OP code benchmarks at 1.4861 seconds.
I'd change to something like:
colors=[1 0 0,
0 1 0,
1 0.5 0,
0 0 1];
nnsamples=samples(samples~=0);
for ii=1:size(nnsamples,1)
line( [ii ii] ,[0 10], 'Marker','.','LineStyle','-','Color',colors(nnsamples(ii),:));
end

Interpolation value from 3D matrices

With 3 vectors and 3 functions, I'm building 3 result matrices. Here's a short and simplified example of what I'm actually doing:
xVec = -0.2:0.05:0.2; % Vector 1
yVec = 0:0.1:0.4; % Vector 2
zVec = 1:3; % Vector 3
[X,Y,Z] = meshgrid(xVec,yVec,zVec);
R1 = (X.^2+Y.^2)./sqrt(Z); % Result matrix 1
R2 = sin(X.^2+Y.^2)./exp(Z); % Result matrix 2
R3 = cos(X.^2+Y.^(1/2)).*(Z.^(1/2)); % Result matrix 3
As of now, I'm calling 6 times the interp1 MATLAB function in order to interpolate (linearly) the 3 result matrices for a specific set of xVec, yVec and zVec values (e.g. xVec = 0.012, yVec = 0.37, and zVec = 1.45). I'm using the interp1 function as I was not able to find a better way of solving this (I think this could be possible with interp2 or interp3 MATLAB functions). By running the MATLAB profiler, I found that the calls to interp1 are taking a lot of time. Hence, I would like to know if there is a faster way of doing this (e.g. using less calls by using the interp2 or interp3 MATLAB function, or maybe even merging my 3 result matrices in a multidimensional array)?
As suggested in the comments, you can use gridded griddedInterpolant. I do not think that there is a standard procedure in MATLAB for optimisation of the interpolation of vector fields (although I did not look thoroughly enough to state this for a fact). Thus, I think you will have to use a different griddedInterpolant for each individual function R1, R2 and R3.
%% griddedInterpolant
[X, Y, Z] = ndgrid(xVec, yVec, zVec);
R1 = (X.^2+Y.^2)./sqrt(Z);
F = griddedInterpolant(X, Y, Z, R1, 'cubic');
figure
subplot(121)
s = slice(Y, X, Z, R1, 0.2, [-0.1 0.1], 2);
set(s, 'EdgeColor', 'none');
for n = 1 : length(s)
set(s(n),'alphadata', get(s(n), 'cdata'), 'facealpha', 'flat')
end
xlabel('y');
ylabel('x');
zlabel('z');
view([-130 30]);
title('Original data');
xqVec = linspace(min(xVec), max(xVec), numPoints); % Vector 1 interpolant
yqVec = linspace(min(yVec), max(yVec), numPoints); % Vector 2 interpolant
zqVec = linspace(min(zVec), max(zVec), numPoints); % Vector 3 interpolant
[Xq, Yq, Zq] = ndgrid(xqVec, yqVec, zqVec);
tic
R1q = F(Xq, Yq, Zq);
toc
subplot(122)
s = slice(Yq, Xq, Zq, R1q, 0.2, [-0.1 0.1], 2);
set(s, 'EdgeColor', 'none');
for n=1:length(s)
set(s(n), 'alphadata', get(s(n), 'cdata'), 'facealpha', 'flat')
end
xlabel('y');
ylabel('x');
zlabel('z');
view([-130 30]);
title('Gridded interpolant');
%% Query at a point
disp(['R1 at [0 0.21 2.1] is ' num2str(F(0, 0.21, 2.1))])

How to create three Y-axis in one graph? [duplicate]

I have 4 sets of values: y1, y2, y3, y4 and one set x. The y values are of different ranges, and I need to plot them as separate curves with separate sets of values on the y-axis.
To put it simple, I need 3 y-axes with different values (scales) for plotting on the same figure.
Any help appreciated, or tips on where to look.
This is a great chance to introduce you to the File Exchange. Though the organization of late has suffered from some very unfortunately interface design choices, it is still a great resource for pre-packaged solutions to common problems. Though many here have given you the gory details of how to achieve this (#prm!), I had a similar need a few years ago and found that addaxis worked very well. (It was a File Exchange pick of the week at one point!) It has inspired later, probably better mods. Here is some example output:
(source: mathworks.com)
I just searched for "plotyy" at File Exchange.
Though understanding what's going on in important, sometimes you just need to get things done, not do them yourself. Matlab Central is great for that.
One possibility you can try is to create 3 axes stacked one on top of the other with the 'Color' properties of the top two set to 'none' so that all the plots are visible. You would have to adjust the axes width, position, and x-axis limits so that the 3 y axes are side-by-side instead of on top of one another. You would also want to remove the x-axis tick marks and labels from 2 of the axes since they will lie on top of one another.
Here's a general implementation that computes the proper positions for the axes and offsets for the x-axis limits to keep the plots lined up properly:
%# Some sample data:
x = 0:20;
N = numel(x);
y1 = rand(1,N);
y2 = 5.*rand(1,N)+5;
y3 = 50.*rand(1,N)-50;
%# Some initial computations:
axesPosition = [110 40 200 200]; %# Axes position, in pixels
yWidth = 30; %# y axes spacing, in pixels
xLimit = [min(x) max(x)]; %# Range of x values
xOffset = -yWidth*diff(xLimit)/axesPosition(3);
%# Create the figure and axes:
figure('Units','pixels','Position',[200 200 330 260]);
h1 = axes('Units','pixels','Position',axesPosition,...
'Color','w','XColor','k','YColor','r',...
'XLim',xLimit,'YLim',[0 1],'NextPlot','add');
h2 = axes('Units','pixels','Position',axesPosition+yWidth.*[-1 0 1 0],...
'Color','none','XColor','k','YColor','m',...
'XLim',xLimit+[xOffset 0],'YLim',[0 10],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
h3 = axes('Units','pixels','Position',axesPosition+yWidth.*[-2 0 2 0],...
'Color','none','XColor','k','YColor','b',...
'XLim',xLimit+[2*xOffset 0],'YLim',[-50 50],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
xlabel(h1,'time');
ylabel(h3,'values');
%# Plot the data:
plot(h1,x,y1,'r');
plot(h2,x,y2,'m');
plot(h3,x,y3,'b');
and here's the resulting figure:
I know of plotyy that allows you to have two y-axes, but no "plotyyy"!
Perhaps you can normalize the y values to have the same scale (min/max normalization, zscore standardization, etc..), then you can just easily plot them using normal plot, hold sequence.
Here's an example:
%# random data
x=1:20;
y = [randn(20,1)*1 + 0 , randn(20,1)*5 + 10 , randn(20,1)*0.3 + 50];
%# plotyy
plotyy(x,y(:,1), x,y(:,3))
%# orginial
figure
subplot(221), plot(x,y(:,1), x,y(:,2), x,y(:,3))
title('original'), legend({'y1' 'y2' 'y3'})
%# normalize: (y-min)/(max-min) ==> [0,1]
yy = bsxfun(#times, bsxfun(#minus,y,min(y)), 1./range(y));
subplot(222), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('minmax')
%# standarize: (y - mean) / std ==> N(0,1)
yy = zscore(y);
subplot(223), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('zscore')
%# softmax normalization with logistic sigmoid ==> [0,1]
yy = 1 ./ ( 1 + exp( -zscore(y) ) );
subplot(224), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('softmax')
Multi-scale plots are rare to find beyond two axes... Luckily in Matlab it is possible, but you have to fully overlap axes and play with tickmarks so as not to hide info.
Below is a nice working sample. I hope this is what you are looking for (although colors could be much nicer)!
close all
clear all
display('Generating data');
x = 0:10;
y1 = rand(1,11);
y2 = 10.*rand(1,11);
y3 = 100.*rand(1,11);
y4 = 100.*rand(1,11);
display('Plotting');
figure;
ax1 = gca;
get(ax1,'Position')
set(ax1,'XColor','k',...
'YColor','b',...
'YLim',[0,1],...
'YTick',[0, 0.2, 0.4, 0.6, 0.8, 1.0]);
line(x, y1, 'Color', 'b', 'LineStyle', '-', 'Marker', '.', 'Parent', ax1)
ax2 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','left',...
'Color','none',...
'XColor','k',...
'YColor','r',...
'YLim',[0,10],...
'YTick',[1, 3, 5, 7, 9],...
'XTick',[],'XTickLabel',[]);
line(x, y2, 'Color', 'r', 'LineStyle', '-', 'Marker', '.', 'Parent', ax2)
ax3 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k',...
'YColor','g',...
'YLim',[0,100],...
'YTick',[0, 20, 40, 60, 80, 100],...
'XTick',[],'XTickLabel',[]);
line(x, y3, 'Color', 'g', 'LineStyle', '-', 'Marker', '.', 'Parent', ax3)
ax4 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k',...
'YColor','c',...
'YLim',[0,100],...
'YTick',[10, 30, 50, 70, 90],...
'XTick',[],'XTickLabel',[]);
line(x, y4, 'Color', 'c', 'LineStyle', '-', 'Marker', '.', 'Parent', ax4)
(source: pablorodriguez.info)
PLOTYY allows two different y-axes. Or you might look into LayerPlot from the File Exchange. I guess I should ask if you've considered using HOLD or just rescaling the data and using regular old plot?
OLD, not what the OP was looking for:
SUBPLOT allows you to break a figure window into multiple axes. Then if you want to have only one x-axis showing, or some other customization, you can manipulate each axis independently.
In your case there are 3 extra y axis (4 in total) and the best code that could be used to achieve what you want and deal with other cases is illustrated above:
clear
clc
x = linspace(0,1,10);
N = numel(x);
y = rand(1,N);
y_extra_1 = 5.*rand(1,N)+5;
y_extra_2 = 50.*rand(1,N)+20;
Y = [y;y_extra_1;y_extra_2];
xLimit = [min(x) max(x)];
xWidth = xLimit(2)-xLimit(1);
numberOfExtraPlots = 2;
a = 0.05;
N_ = numberOfExtraPlots+1;
for i=1:N_
L=1-(numberOfExtraPlots*a)-0.2;
axesPosition = [(0.1+(numberOfExtraPlots*a)) 0.1 L 0.8];
if(i==1)
color = [rand(1),rand(1),rand(1)];
figure('Units','pixels','Position',[200 200 1200 600])
axes('Units','normalized','Position',axesPosition,...
'Color','w','XColor','k','YColor',color,...
'XLim',xLimit,'YLim',[min(Y(i,:)) max(Y(i,:))],...
'NextPlot','add');
plot(x,Y(i,:),'Color',color);
xlabel('Time (s)');
ylab = strcat('Values of dataset 0',num2str(i));
ylabel(ylab)
numberOfExtraPlots = numberOfExtraPlots - 1;
else
color = [rand(1),rand(1),rand(1)];
axes('Units','normalized','Position',axesPosition,...
'Color','none','XColor','k','YColor',color,...
'XLim',xLimit,'YLim',[min(Y(i,:)) max(Y(i,:))],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
V = (xWidth*a*(i-1))/L;
b=xLimit+[V 0];
x_=linspace(b(1),b(2),10);
plot(x_,Y(i,:),'Color',color);
ylab = strcat('Values of dataset 0',num2str(i));
ylabel(ylab)
numberOfExtraPlots = numberOfExtraPlots - 1;
end
end
The code above will produce something like this:

formatting plotyy with two vectors for each y axis

I have a plotyy figure in MATLAB with 2 vectors in on each y axis.
plotyy(x1,[y1(:),y2(:)], x1,[y3(:),y4(:)])
I need to format each of the lines separately, but can not find the documentation about how to do this. Can someone please me show an example?
Does the following example code help?
%# Generate some data
N = 20;
X = (1:N)';
Y1 = randn(N, 1);
Y2 = randn(N, 1);
Y3 = randn(N, 1) - 50;
Y4 = randn(N, 1) - 50;
%# Perform the plotyy, returning an axes handle, and a handle for both figures
[Axes, fig1, fig2] = plotyy(X, [Y1 Y2], X, [Y3 Y4]);
%# Change the format of Y1 and Y2 (separately)
set(fig1(1), 'LineStyle', ':');
set(fig1(2), 'LineStyle', '--');
%# Change the format of Y3
set(fig2(1), 'LineStyle', '-.');
In the above code, the figure handle fig1 corresponds to the first y-plot, ie Y1 and Y2, and I can access the individual lines by indexing fig1 with 1 and 2.
Similarly, the figure handle fig2 corresponds to the second y-plot, ie Y3 and Y4, and I access Y3 by indexing this handle with 1. I could also access Y4 with fig2(2), if I so desired.