Get data vector from stairstep plot Matlab - matlab

How can one get the data vectors from the output of the stairs function in Matlab? I tried the following
h = stairs(x,y);
Then I get the data from the handle:
x = h.XData;
y = h.YData;
but when x and y are plotted, they look as a piece-wise function, not the stairs.
Any help is appreciated.
Thanks!

The data necessary to display a stairs plot are relatively easy to generate by yourself.
Assuming you have x and y. To generate 2 vectors xs and ys such as plot(xs,ys) will display the same thing than stairs(x,y), you can use the following 2 steps method:
replicate each element of x and y
offset the new vectors by one element (remove the first point of one vector and the last point of the other)
Example with code:
%% demo data
x = (0:20).';
y = [(0:10),(9:-1:0)].' ;
hs = stairs(x,y) ;
hold on
%% generate `xs` and `ys`
% replicate each element of `x` and `y` vector
xs = reshape([x(:) x(:)].',[],1) ;
ys = reshape([y(:) y(:)].',[],1) ;
% offset the 2 vectors by one element
% => remove first `xs` and last `ys`
xs(1) = [] ;
ys(end) = [] ;
% you're good to go, this will plot the same thing than stairs(x,y)
hp = plot(xs,ys) ;
% and they will also work with the `fill` function
hf = fill(xs,ys,'g') ;

Matlab documentation explicit says:
[xb,yb] = stairs(___) does not create a plot, but returns matrices xb
and yb of the same size, such that plot(xb,yb) plots the stairstep
graph.

Related

Convert large xyz file into gridded data (Matlab)

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)

Matlab: repmat code explanation

Can anyone explain the two lines of code highlighted below which use repmat? This is taken directly from the MathWorks documentation for learning data analysis:
bin_counts = hist(c3); % Histogram bin counts
N = max(bin_counts); % Maximum bin count
mu3 = mean(c3); % Data mean
sigma3 = std(c3); % Data standard deviation
hist(c3) % Plot histogram
hold on
plot([mu3 mu3],[0 N],'r','LineWidth',2) % Mean
% --------------------------------------------------------------
X = repmat(mu3+(1:2)*sigma3,2,1); % WHAT IS THIS?
Y = repmat([0;N],1,2); % WHY IS THIS NECESSARY?
% --------------------------------------------------------------
plot(X,Y,'g','LineWidth',2) % Standard deviations
legend('Data','Mean','Stds')
hold off
Could anyone explain the X = repmat(...) line to me? I know it will be plotted for the 1 and 2 standard deviation lines.
Also, I tried commenting out the Y = ... line, and the plot looks the exact same, so what is the purpose of this line?
Thanks
Lets break the expression into multiple statements
X = repmat(mu3+(1:2)*sigma3,2,1);
is equivalent to
% First create a row vector containing one and two standard deviations from the mean.
% This is equivalent to xvals = [mu3+1*sigma3, mu3+2*sigma3];
xval = mu3 + (1:2)*sigma3;
% Repeat the matrix twice in the vertical dimension. We want to plot two vertical
% lines so the first and second point should be equal so we just use repmat to repeat them.
% This is equivalent to
% X = [xvals;
% xvals];
X = repmat(xval,2,1);
% To help understand how repmat works, if we had X = repmat(xval,3,2) we would get
% X = [xval, xval;
% xval, xval;
% xval, xval];
The logic is similar for the Y matrix except it repeats in the column direction. Together you end up with
X = [mu3+1*sigma3, mu3+2*sigma3;
mu3+1*sigma3, mu3+2*sigma3];
Y = [0, 0;
N, N];
When plot is called it plots one line per column of the X and Y matrices.
plot(X,Y,'g','LineWidth',2);
is equivalent to
plot([mu3+1*sigma3; mu3+1*sigma3], [0, N], 'g','LineWidth',2);
hold on;
plot([mu3+2*sigma3; mu3+2*sigma3], [0, N], 'g','LineWidth',2);
which plots two vertical lines, one and two standard deviations from the mean.
If you comment out Y then Y isn't defined. The reason the code still worked is probably that the previous value of Y was still stored in the workspace. If you run the command clear before running the script again you will find that the plot command will fail.

Quad in a cell of handle functions

I have two lists of functions, for instance: log(n*x), n=1:2017 and cos(m*x), m=1:6. I want/need to construct the matrix product of these vectors and then integrating each element of the matrix between 10 and 20.
I have read this post:
Matrix of symbolic functions
but I think that it is not useful for this problem.
I'm trying to do this by using a loop but I can not get it.
Thanks in advance for reading it.
You can solve this problem by assigning the appropriate vectors to n and m as follows:
n = (1:2017)'; % column vector
m = 1:6; % row vector
syms x;
l = log(n*x); % column vector of logs
c = cos(m*x); % row vector of cos
product = l*c; % matrix product
i = int(product, x, 10, 20); % integral from 10 to 20
iDouble = double(i); % convert the result to double

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: work with 2NxN matrix

I have a matrix 2NxN.
And I want get some parametrs by this matrix. For example it:
How, I can do it?
You may want to break your 12x6 matrix, into two 6x6 matrix; let's say: Z and Zb (last one for z bar). Odd rows are Z and evens are Zb.
Considering M to be the combined matrices:
Z = M(1:2:end,:)
Zb = M(2:2:end,:)
read about the colon(:) operator and end to see what 1:2:end means.
Hope it helps.
From what I understand here are the first three:
% Random Matrix
% Needs to be defined before the functions since the functions look for
% the m variable
m = rand(12,6);
% Function 1
p = #(i,j) sign(m(i,j)+m(i+1,j)) * max(abs(m(i,j)),abs(m(i+1,j)));
p(2,2)
% Function 2 - Avg of row
pavg = #(i) mean(m(i,:));
pavg(2)
% Function 3
c = #(i,j) abs(m(i,j)+m(i+1,j)) / (abs(m(i,j)) + abs(m(i+1,j)));
c(2,2)