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
Related
I conducted a 2D fourier transform on a 4436413x3 matrix using the matlab fft2 command (this one: https://www.mathworks.com/help/matlab/ref/fft2.html). The product is a 4436413x3 matrix containing complex values. When I try to plot the data, I end up with a graph that is all one color or an error message that references the complex values in my data.
I have tried interpolating to create a 2D set of values using the griddata() function, however, when applied to my 3D dataset, this returns a 1D vector equal to the z-column in my original 3D dataset. My 3D dataset consists of x, y, and z points, and in my attempt to interpolate I used vq = griddata(x,y,z,x,y). I had also tried to create a 4436412x3 meshgrid for my query points (using [xq, yq] = meshgrid(4436412, 3), and then using xq and yq as my query points), but this was returning NaN.
When I run
Y = fft2(x);
imagesc(abs(fftshift(Y)))
I get a single purple box.
When I run
Y = fft2(x);
imagesc(Y)
I get the following error message:
Error using image
Complex values are not supported. Specify the color data as numeric or logical values.
Error in imagesc (line 52)
hh = image(varargin{:}, 'CDataMapping', 'scaled');
To apply the FFT, you need data to be sampled on a regular grid. Your data represents (x,y,z) coordinates of points. Here's how to use griddata to resample these coordinates onto a regular (x,y) grid:
% Generate example data, let's say x and y are in the range [-3,3]:
n = 62500;
x = rand(n, 1) * 6 - 3;
y = rand(n, 1) * 6 - 3;
z = sin(4*x) + cos(2*y); % an example function
data = [x,y,z]; % This is a 4436413x3 array with (x,y,z) coordinates
% Interpolate z values onto a regular (x,y) grid:
[xq, yq] = meshgrid(linspace(min(x), max(x), sqrt(n)), ...
linspace(min(y), max(y), sqrt(n)));
zq = griddata(x, y, z, xq, yq);
% griddata doesn't extrapolate, writes NaN instead. Let's fill those
% in with zeros (maybe a different value is more meaningful in your
% application).
zq(isnan(zq)) = 0;
% Now you can apply a 2D Fourier transform:
Z = fft2(zq);
imshow(log(abs(fftshift(Z))), []);
I have a large XYZ file (300276x3, this file includes x and y coordinates (not lat/lon, but polar stereographic) and elevation z) and I'm wondering if it would be possible to convert this into a gridded dataset (n x m matrix). The xyz file can be downloaded from:
https://wetransfer.com/downloads/4ae4ce51072dceef93486314d161509920191021213532/48e4ee68c17269bd6f7a72c1384b3c9a20191021213532/60b04d
and imported in matlab by:
AIS_SEC = importdata('AIS_SEC.xyz');
I tried:
X= XYZ(:,1);
Y= XYZ(:,2);
Z= XYZ(:,3);
xr = sort(unique(X));
yr = sort(unique(Y));
gRho = zeros(length(yr),length(xr));
gRho = griddata(X,Y,Z,xr,yr')
imagesc(gRho)
Requested 300276x300276 (671.8GB) array exceeds maximum array size preference. Creation of arrays
greater than this limit may take a long time and cause MATLAB to become unresponsive. See array size
limit or preference panel for more information.
I tried:
% Get coordinate vectors
x = unique(XYZ(:,1)) ;
y = unique(XYZ(:,2)) ;
% dimensions of the data
nx = length(x) ;
ny = length(y) ;
% Frame matrix of grid
D = reshape(XYZ(:,3),[ny,nx]) ;
% flip matrix to adjust for plot
H = flipud(H) ;
% Transpose the matrix
H = H' ; % Check if is required
surf(x,y,H) ;
Error using reshape
To RESHAPE the number of elements must not change.
I can now plot the nx3 file with scatter3 (see image)
scatter3(XYZ(:,1),XYZ(:,2),XYZ(:,3),2,XYZ(:,3)) ;
colorbar
But I'd like to do it with imagesc. Hence, I would like to convert the nx3 file into a nxm matrix (in raster/gridded format) and as en extra I would like it as a geotiff file for use in QGIS.
Thanks!
You were almost there... Looking at the message about array size you got, it seems likely that the result of unique(X) results in 300276 unique values, probably due to some noisy data.
So instead of using griddata with these large X and Y vectors, you can define some new ones on the domain you need:
% make some sample data
N = 1000;
xv = linspace(-10,10,N);
yv = linspace(-10,10,N);
[XV,YV] = meshgrid(xv,yv);
ZV = XV.^2 + YV.^2;
% make into long vectors:
X = XV(:);
Y = YV(:);
Z = ZV(:);
% make x and y vector to interpolate z
N = 50; % size of new grid
xv = linspace(min(X), max(X), N);
yv = linspace(min(Y), max(Y), N);
[XV,YV] = meshgrid(xv,yv);
% use griddata to find right Z for each x,y pair
ZV_grid = griddata(X,Y,Z,XV,YV);
% look at result
figure();
subplot(211)
imagesc(ZV);
subplot(212);
imagesc(ZV_grid)
So suppose you pass some matrix N to hist3 in Matlab, which is a m-by-2 matrix, simply for an example purposes. Where the first column is your variable X and column 2 corresponds to your variable Y.
When you run the cnt = hist3(N, {bins_X bins_Y}), you would get a m-by-m matrix. Rows here are which variable, X or Y?
OP seems to have solved his problem. However, I am leaving a code snippet exemplifying hist3's output indexing in case anyone finds it useful.
% Simulate random 2-column matrix
X = randn(1e5,2);
% Scale x-axis data to see label distinction
X(:,1) = X(:,1)*10;
% Define bins
bin_x = linspace(-30,30,80);
bin_y = linspace(-3,3,100);
% Get frequency grid
cnt = hist3(X,{bin_x,bin_y});
% Plot frequency values with surf
[x,y] = meshgrid(bin_x,bin_y);
figure
surf(x,y,cnt')
title('Original hist3 output')
xlabel('First Column')
ylabel('Second Column')
zlabel('Frequency')
% Access and modify cnt, and plot again
cnt(end,1:10) = 60;
cnt(25:55,1:55)= 0;
figure
surf(x,y,cnt')
title('Modified hist3 output')
xlabel('First Column')
ylabel('Second Column')
zlabel('Frequency')
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
I have a set of 2D points (not ordered) forming a closed contour, and I would like to resample them to 14 equally spaced points. It is a contour of a kidney on an image. Any ideas?
One intuitive approach (IMO) is to create an independent variable for both x and y. Base it on arc length, and interpolate on it.
% close the contour, temporarily
xc = [x(:); x(1)];
yc = [y(:); y(1)];
% current spacing may not be equally spaced
dx = diff(xc);
dy = diff(yc);
% distances between consecutive coordiates
dS = sqrt(dx.^2+dy.^2);
dS = [0; dS]; % including start point
% arc length, going along (around) snake
d = cumsum(dS); % here is your independent variable
perim = d(end);
Now you have an independent variable and you can interpolate to create N segments:
N = 14;
ds = perim / N;
dSi = ds*(0:N).'; %' your NEW independent variable, equally spaced
dSi(end) = dSi(end)-.005; % appease interp1
xi = interp1(d,xc,dSi);
yi = interp1(d,yc,dSi);
xi(end)=[]; yi(end)=[];
Try it using imfreehand:
figure, imshow('cameraman.tif');
h = imfreehand(gca);
xy = h.getPosition; x = xy(:,1); y = xy(:,2);
% run the above solution ...
Say your contour is defined by independent vector x and dependent vector y.
You can get your resampled x vector using linspace:
new_x = linspace(min(x),max(x),14); %14 to get 14 equally spaced points
Then use interp1 to get new_y values at each new_x point:
new_y = interp1(x,y,new_x);
There are a few interpolation methods to choose from - default is linear. See interp1 help for more info.