Extract data from ezplot in MATLAB - matlab

I am trying to extract data from an ezplot, but when I plot the extracted data, I don't get the same graph (a and b are different)...
Could anybody elaborate on what's wrong?
Here is the code:
h = #(x,y)(x-((1/0.0175)*(y/5500)*(1+(y/5500)^9)))
a = ezplot(h,[0,700,0,7000]);
t = get(a,'xdata');
M = get(a,'ydata');
theta = transpose(t)
figure
b = plot(theta,M)
ezplot produces
whilst plot produces
This is what I get by extracting from the contour, there is still a straight line 3

ezplot returns a contour object. To extract the x and y data you need to use get(a,'contourMatrix'). Then the x data will be in the first column and the y data in the second column as
t = get(a,'contourMatrix');
x = t(1, :);
y = t(2, :);
Putting this altogether for your example we get
h = #(x,y)(x-((1/0.0175)*(y/5500)*(1+(y/5500)^9)))
a = ezplot(h,[0,700,0,7000]);
t = get(a,'contourMatrix');
x = t(1, :);
y = t(2, :);
figure;
b = plot(x, y);
xlabel('x');
ylabel('y');
title('({x}-(({1}/{0.0175}) ({y}/{5500}) ({1}+({y}/{5500})^{9}))) = {0}');
The resulting ezplot is
and the same from plot

You are getting the x and y axis values in calling get(a,'xdata') and get(a,'ydata'). That is the reason you're getting the straight line.
Try this instead:
h = #(x,y)(x-((1/0.0175)*(y/5500)*(1+(y/5500)^9)));
ezplot(h,[0,700,0,7000]);
a= get(gca,'Children');
l=get(a,'Children');
t = get(l,'xdata');
M = get(l,'ydata');
theta = transpose(t);
figure
b = plot(theta,M);
Sources:
Handle Graphics: Modifying Plots
How do I extract data from MATLAB figures?

Related

Fitting a n ordered polynomial

I was trying to plot a regression curve:
coef_fit = polyfit(norm_dist,norm_time,7);
y_fit = polyval(coef_fit,xlim);
plot(xlim,y_fit,'r');
But it is always plotting a line respective of the order I pass.
The problem is that the x values you are using are the output ot xlim, which is a length-2 vector. You need to define an x vector with more values:
norm_dist = sort(5*randn(1,50) + (1:50)); %// example x values
norm_time = 5*randn(1,50) + (1:50).^2; %// example y values
x = linspace(min(norm_dist), max(norm_dist), 200); %// define x values for plot
coef_fit = polyfit(norm_dist,norm_time,7);
y_fit = polyval(coef_fit,x);
plot(x,y_fit,'r');
hold on
plot(norm_dist, norm_time, 'b.') %// plot original points for comparison

Generate heatmap with coordinates and data stored in vectors

Let A be an n by 3 matrix, such that the first two columns are all ordered pairs of the form (5*i,5*i) for i from 1 to 200. The third column contains values from 0 to 1, which I will call intensities. I want to make a 1000 by 1000 plot so that the rectangle at (5*i,5*i) is shaded with intensity described by the third column entry.
I'm familiar with the heatmap function and imshow, but I don't see a way to include this "scaling by 5" to make a nice plot. And of course in general the x and y coordinates may not be scaled by the same amount.
Is there a nice way to do this in Matlab?
With imagesc it's actually pretty simple:
First some example data:
%// generate example data
ii = 1:200;
[xx,yy] = meshgrid(ii);
A(:,1) = 5*xx(:);
A(:,2) = 5*yy(:);
A(:,3) = randi([0,1],1,40000);
Actual answer
n = 200;
%// reshape data
D = reshape( A(:,3),n,n );
%// heatmap
imagesc(A(:,1),A(:,2),D)
colormap(gray)
caxis([0,1])
gives:
Important notice
If your coordinates are not sorted as required for imagesc you can sort them with:
A = sortrows(A,[2,1]);
Clown Example
%// original image
load clown
I = reshape(1:numel(X),size(X));
[R,C] = ind2sub(size(X),I);
A(:,1) = R(:);
A(:,2) = C(:);
A(:,3) = X(:);
D = reshape( A(:,3),200,320 );
figure(1)
subplot(1,3,1)
imagesc(A(:,1),A(:,2),D)
%// shuffled image -> shuffled data
shuffle = randperm(320*200);
A = A(shuffle,:);
D = reshape( A(:,3),200,320 );
subplot(1,3,2)
imagesc(A(:,1),A(:,2),D)
%// sorted image
A = sortrows(A,[2,1]);
D = reshape( A(:,3),200,320 );
subplot(1,3,3)
imagesc(A(:,1),A(:,2),D)
You see, even if your coordinates are sorted like a mess, you can rebuild the image with sortrows.
See this
function DrawHeatmap(X,Y,Z)
%DRAWHEATMAP Draw a 2D heatmap for (X,Y) coordinates whose values are in Z
% X, Y , Z must be columns
% By: Eng. Osama Talaat Abdel-Hafiz - PhD Student
% Egypt - Sept 2017
if size(X,2)==1 && size(Y,2)==1 && size(Z,2)==1
F = scatteredInterpolant(X,Y,Z); % create a function from interpolation
[X,Y] = meshgrid(min(X):0.1:max(X),min(Y):0.1:max(Y));
Z = F(X,Y);
contourf(X, Y, Z, linspace(floor(min(min(Z))),ceil(max(max(Z))),400), 'LineColor','none')
colorbar;
else
error('X, Y , Z must be columns')
end
end

plotting scatter3 and surf plots from loop in matlab

I want to plot scatter3 and surf plots from a loop. Below is my code but it isn't working...not sure where I'm going wrong but clearly something is wrong with the z matrix?
for e = 1:10;
x = rand(1,3);
y = rand(1,3);
A = x+y;
subplot(2,2,1)
p = find(A(:,1) > 1.1 & A(:,1) < 1.6);
Result = A(p,:);
scatter3(Result(:,1), Result(:,2), Result(:,3))
hold on
z(e,:) = [Result(1) Result(2) Result(3)];
end
subplot(2,2,2)
surf(z)
I will reiterate what I said in my comment to you. I got this error message when trying to run your code: Attempted to access Result(1); index out of bounds because numel(Result)=0. This is because your p condition isn't satisfied - MATLAB could not find any elements in the first column that are between 1.1 and 1.6.
As such, what I would suggest you do is check to see if Result is empty before trying to access the value itself. However, I would suggest you don't write a loop and generate all of the random values at once, then do the filtering with the Boolean conditions. Therefore, the equivalent code without using a loop would be this:
x = rand(10,3);
y = rand(10,3);
A = x+y;
p = A(:,1) > 1.1 & A(:,1) < 1.6;
z = A(p,:);
figure;
subplot(2,1,1);
scatter3(z(:,1), z(:,2), z(:,3));
subplot(2,1,2);
surf(z);
We generate 10 3D points for x and y at the beginning, then add these and store this into A. Next, we find the rows in A that are between 1.1 and 1.6 in the first column and store this as a logical array. We then use this array to index into A and store the results into z. This is the recommended approach if you want to extract certain elements into an array rather than using find.
Once we obtain z, we plot these points with scatter, then also find a surface plot with surf for the same matrix. BTW, I've fixed your subplot as you are only creating two plots, yet you are allocating space for 4 plots.
If you're absolutely bent on using your code, you would simply do this:
z = []; %// Change
for e = 1:10
x = rand(1,3);
y = rand(1,3);
A = x+y;
subplot(2,1,1)
p = find(A(:,1) > 1.1 & A(:,1) < 1.6);
Result = A(p,:);
scatter3(Result(:,1), Result(:,2), Result(:,3))
hold on
if ~isempty(Result) %// Change here
z = [z; Result(1) Result(2) Result(3)]; %// Change
end
end
subplot(2,1,2)
surf(z)
What's important is the initialization of z. I made this empty, and we only add to z if Result is not empty - this will happen if you generate a number that is not between 1.1 and 1.6.

Matlab smooth a 3d mesh plot

Hi I have a set of data A with each element corresponding to an x and y combination. When I plot this dat using mesh I get a graph with many spikes on it. This is not unnexpected but I would like a way to smooth these out to get a smooth surface.
I've tried to use the smooth3 command but cannot figure out how to make the suitable input.
Any help would be appreciated. Thanks
This is how my data is generated.
function v = f(x,y) % Not actual function
return x*rand()+y*rand()
end
x = 0.05:0.01:0.95;
y = 0.05:0.01:0.95;
o = zeros(length(x),length(y));
A = zeros(length(x), length(y));
for k = 1:5
for i = 1:length(x)
for j = 1:length(y)
o(i,j) = f([x(i), y(j)]);
end
end
A= A+o;
end
A = A/5;
This is what produces the plot.
[X,Y] = meshgrid(x);
mesh(A)
my be you can try a convolution of your variable A with a filter(the following is an example of a Gaussian filter).
C = conv2(A,fspecial('gaussian', hsize, sigma));
check conv2 and fspecial in matlab help

Plot gradient of a function which is a matrix in MATLAB

I would like to plot the gradient of the following function in MATLAB.
g(x,y) = [(x^2)-1; -y]
My code is:
x = linspace(-3,3);
y = linspace(-3,3);
[xx, yy] = meshgrid(x,y);
z = [xx.^2-1;-yy];
[dx,dy] = gradient(z,.3,.3);
contour(x,y,z)
hold on
quiver(x,y,dx,dy)
But I'm just getting this error:
The size of Y must match the size of Z or the number of rows
of Z.
I've no idea how I could make the size of both match. y is a 1x100 matrix and z a 200x100. To match them I would need y to be a 1x200 or z to be 100x100, but would I be able to plot it then?
Instead of
z = [xx.^2-1;-yy];
try each component separately:
z1 = [xx.^2-1];
z2 = [-yy];
[dx,dy] = gradient(z1,.3,.3);
contour(x,y,z1)
%etc.
Use hold on again if you really want them in the same plot.