I have to interpolate wind directions. The data is given for every 1000 [ft]. for example:
%winddata input in feet en degrees
x=0:1000:10000;
grad=[340 350 360 1 10 20 30 35 34 36 38];
The interpolation works great, i use the function interp1. (please see code below.) However, the step from 360 degrees to 1 degrees is a problem. I want Matlab to interpolate from 360 to 1 degree directly (clockwise), instead of anticlockwise with the values degreasing from 360-359-358-...3-2-1. That doesnt make sense when you interpolate wind directions.
How can i command Matlab to repeate the x-axis and values every 360 degrees?
clear all;clc;
h=2000;
%winddata input in feet en degrees!
x=0:1000:10000;
degrees=[340 350 360 1 10 20 30 35 34 36 38];
%conversion to SI:
x=0.3048*x;
u=0:1:max(x);
yinterp1 = interp1(x,degrees,u,'linear');
figure(3)
plot(degrees,x,'bo',yinterp1,u,'-r')
xlabel('wind direction [degrees]')
ylabel('height [m]')
title 'windspeed lineair interpolated with function interp'
The problem is that Matlab, as smart as it is, doesn't realise that you're working with degrees, so therefore it sees no reason that 360 = 0. Therefore I believe your problem isn't with finding a way to repeat the plot every 360 degrees, but rather with the data you are feeding in to your interp1 function, as currently you are telling it there is a straight line between the points (0, 950) and (360, 750).
The easiest, but ugliest, method would be to just add 360 to your lower values, so your degrees vector read:
degrees = [340 350 360 361 370 380 390 395 394 396 398];
and then subtract 360 from your degrees and yinterp1 vectors:
clear all;clc;
h=2000;
%winddata input in feet en degrees!
x=0:1000:10000;
degrees=[340 350 360 361 370 380 390 395 394 396 398];
%conversion to SI:
x=0.3048*x;
u=0:1:max(x);
yinterp1 = interp1(x,degrees,u,'linear');
figure(3)
plot(degrees-360,x,'bo',yinterp1-360,u,'-r')
xlabel('wind direction [degrees]')
ylabel('height [m]')
title 'windspeed lineair interpolated with function interp'
xlim([-180 180]);
The obvious problem with this is it isn't able to be applied for all cases, but if you just need a one off, then it works well.
For a more generic solution you could have it so you manually enter a point below which values have 360 added to them:
clear all;clc;
h=2000;
% --------------------- Manual cutoff for rectification -------------------
limitDegrees = 180;
% -------------------------------------------------------------------------
%winddata input in feet en degrees!
x=0:1000:10000;
degrees=[340 350 360 1 10 20 30 35 34 36 38];
%conversion to SI:
x=0.3048*x;
u=0:1:max(x);
indecesTooSmall = find(degrees <= limitDegrees);
oneVec = zeros(size(degrees));
oneVec(indecesTooSmall) = 1;
vecToAdd = 360*ones(size(degrees));
vecToAdd = vecToAdd .* oneVec;
newDegrees = degrees + vecToAdd;
yinterp1 = interp1(x,newDegrees,u,'linear');
figure(3)
plot(newDegrees-360,x,'bo',yinterp1-360,u,'-r')
xlabel('wind direction [degrees]')
ylabel('height [m]')
title 'windspeed lineair interpolated with function interp'
xlim([-180 180]);
Both of the above solutions give the following:
EDIT: Substantially easier solution, just use rad2deg(unwrap(deg2rad(degrees))), or try to find an unwrap which works for degrees.
Related
I know how to calculate the line parameter defined as x below for one layer, considering the given wavelength range 50 to 550 um. Now I want to repeat this calculation for all 10 layers. all the other parameters remain as a constant while temperature varies from layer 1 to 10.Any suggestion would be greatly appreciated.
wl=[100 200 300 400 500]; %5 wavelengths, 5 spectral lines
br=[0.12 0.56 0.45 0.67 0.89]; % broadening parameter for each wavelength
T=[101 102 103 104 105 106 107 108 109 110];% temperature for 10 layers
wlall=linspace(50,550,40);%all the wavelength in 50um to 550 um range
% x is defined as,
%(br*wl/(br*br + (wlall-wl)^2))*br;
%If I do a calculation for the first line
((br(1)*T(1)*wl(1))./(br(1)*br(1)*(T(1)) + (wlall(:)-wl(1)).^2))*br(1)*T(1)
%Now I'm going to calculate it for all the lines in the first layer
k= repmat(wlall,5,1);
for i=1:5;
kn(i,:)=(br(i)*T(1)* wl(i)./(br(i)*br(i)*T(1) + (k(i,:)-
wl(i)).^2))*br(i)*T(1);
end
%Above code gives me x parameter for all the wavelengths in the
%given range( 50 to 550 um) in the first layer, dimension is (5,40)
% I need only the maximum value of each column
an=(kn(:,:)');
[ll,mm]=sort(an,2,'descend');
vn=(ll(:,1))'
%Now my output has the dimension , (1,40) one is for the first layer, 40 is
%for the maximum x parameter corresponding to each wavelength in first layer
%Now I want to calculate the x parameter in all 10 layers,So T should vary
%from T(1) to T(10) and get the
%maximum in each column, so my output should have the dimension ( 10, 40)
You just need to run an extra 'for' loop for each value of 'T'. Here is an example:
clc; close all; clear all;
wl=[100 200 300 400 500]; %5 wavelengths, 5 spectral lines
br=[0.12 0.56 0.45 0.67 0.89]; % broadening parameter for each wavelength
T=[101 102 103 104 105 106 107 108 109 110];% temperature for 10 layers
wlall=linspace(50,550,40);%all the wavelength in 50um to 550 um range
% x is defined as,
%(br*wl/(br*br + (wlall-wl)^2))*br;
%If I do a calculation for the first line
((br(1)*T(1)*wl(1))./(br(1)*br(1)*(T(1)) + (wlall(:)-wl(1)).^2))*br(1)*T(1)
%Now I'm going to calculate it for all the lines in the first layer
k= repmat(wlall,5,1);
for index = 1:numel(T)
for i=1:5
kn(i,:, index)=(br(i)*T(index)* wl(i)./(br(i)*br(i)*T(index) + (k(i,:)- wl(i)).^2))*br(i)*T(index);
end
an(:, :, index) = transpose(kn(:, :, index));
vn(:, index) = max(an(:, :, index), [], 2);
end
vn = transpose(vn);
Using matlab, I want to apply transform contain of rotate and translate to 2d points.
for example my points are:
points.x=[1 5 7 100 52];
points.y=[42 96 71 3 17];
points.angle=[2 6 7 9 4];
the value of rotate is:30 degree
the value of x_translate is 5.
the value of y_translate is 54.
can any body help me to write matlab code for apply this transform to my points and calculate new coordinate of points after transform?
I don't know what you mean by points.angle since the angle of the points with respect to origin (in a trigonometric sense) is already defined by atand2(y,x)
Here is the code:
clear;clc
oldCoord = [1 5 7 100 52;42 96 71 3 17];
newCoord = zeros(size(oldCoord));
theta = 30 * pi/180;
T = #(theta) [cos(theta), -sin(theta); sin(theta) , cos(theta)];
trans = [5;54];
for m = 1:size(oldCoord,2)
newCoord(:,m) = T(theta) * oldCoord(:,m) + trans;
end
Result:
oldCoord =
1 5 7 100 52
42 96 71 3 17
newCoord =
-15.1340 -38.6699 -24.4378 90.1025 41.5333
90.8731 139.6384 118.9878 106.5981 94.7224
I have a series of ordered points (X, Y, Z) and I want to plot a 3D histogram, any suggestions?
I'm trying to do it by this tutorial http://www.mathworks.com/help/stats/hist3.html , but points are random here and presented as a function. My example is easier, since i already know the points.
Furthermore, depending on the number value of Z coordinate, i'd like to colour it differently. E.g. Max value - green, min value - red. Similar as in this case Conditional coloring of histogram graph in MATLAB, only in 3D.
So, if I have a series of points:
X = [32 64 32 12 56 76 65]
Y = [160 80 70 48 90 80 70]
Z = [80 70 90 20 45 60 12]
Can you help me with the code for 3D histogram with conditional coloring?
So far the code looks like this:
X = [32 64 32 12 56 76 65];
Y= [160 80 70 48 90 80 70];
Z= [80 70 90 20 45 60 12];
A = full( sparse(X',Y',Z'));
figure;
h = bar3(A); % get handle to graphics
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( A(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
set(h(k),'CData', nz); % set the new colors
end
colorbar;
Now I just have to clear the lines and design the chart to make it look useful. But how would it be possible to make a bar3 without the entire mesh on 0 level?
Based on this answer, all you need to do is rearrange your data to match the Z format of that answer. After than you might need to remove edgelines and possibly clear the zero height bars.
% Step 1: rearrange your data
X = [32 64 32 12 56 76 65];
Y= [160 80 70 48 90 80 70];
Z= [80 70 90 20 45 60 12];
A = full( sparse(X',Y',Z'));
% Step 2: Use the code from the link to plot the 3D histogram
figure;
h = bar3(A); % get handle to graphics
set(h,'edgecolor','none'); % Hopefully this will remove the lines (from https://www.mathworks.com/matlabcentral/newsreader/view_thread/281581)
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( A(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
nz(nz==0) = NaN; % This bit makes all the zero height bars have no colour
set(h(k),'CData', nz); % set the new colors. Note in later versions you can do h(k).CData = nz
end
colorbar;
I am struggling with the concepts behind plotting a surface polar plot.
I am trying to plot the values measured by a sensor at a combination of different angles over a hemisphere.
I have an array containing the following information:
A(:,1) = azimuth values from 0 to 360º
A(:,2) = zenith values from 0 to 90º
A(:,3) = values measured at the combination of angles of A(:,1) and A(:,2)
For example, here is a snippet:
0 15 0.489502132167206
0 30 0.452957556748497
0 45 0.468147850273115
0 60 0.471115818950192
0 65 0.352532182508945
30 15 0.424997863795610
30 30 0.477814980942155
30 45 0.383999653859467
30 60 0.509625464595446
30 75 0.440940431784788
60 15 0.445028058361392
60 30 0.522388502880219
60 45 0.428092266657885
60 60 0.429315072676194
60 75 0.358172892912138
90 15 0.493704001125912
90 30 0.508762762699997
90 45 0.450598496609200
90 58 0.468523071441297
120 15 0.501619699042408
120 30 0.561755273071577
120 45 0.489660355057938
120 60 0.475478615354648
120 75 0.482572226928475
150 15 0.423716506205776
150 30 0.426735372570756
150 45 0.448548968227972
150 60 0.478055144126694
150 75 0.437389584937356
To clarify, here is a piece of code that shows the measurement points on a polar plot.
th = A(:,1)*pi/180
polar(th,A(:,2))
view([180 90])
This gives me the following plot:
I would like now to plot the same thing, but instead of the points, use the values of these points stored in A(:,3). Then, I would like to interpolate the data to get a colored surface.
After some research, I found that I need to interpolate my values over a grid, then translate to Cartesian coordinates. From there I do not know how to proceed. Could someone point me in the right direction?
I have trouble getting the concept of the interpolation, but this is what I have attempted:
x1 = linspace(0,2*pi,100)
x2 = linspace(0,90,100)
[XX,YY] = meshgrid(x1,x2)
[x,y] = pol2cart(th,A(:,2))
gr=griddata(x,y,A(:,3),XX,YY,'linear')
With this piece of code, your example data points are converted into cartesian coords, and then plotted as "lines". The two tips of a line are one data point and the origin.
az = bsxfun(#times, A(:,1), pi/180);
el = bsxfun(#times, A(:,2), pi/180);
r = A(:,3);
[x,y,z] = sph2cart(az,el,r);
cx = 0; % center of the sphere
cy = 0;
cz = 0;
X = [repmat(cx,1,length(x));x'];
Y = [repmat(cy,1,length(y));y'];
Z = [repmat(cz,1,length(z));z'];
Still thinking how to interpolate the data so you can draw a sphere. See my comments to your question.
I have two vectors which are paired values
size(X)=1e4 x 1; size(Y)=1e4 x 1
Is it possible to plot a contour plot of some sort making the contours by the highest density of points? Ie highest clustering=red, and then gradient colour elsewhere?
If you need more clarification please ask.
Regards,
EXAMPLE DATA:
X=[53 58 62 56 72 63 65 57 52 56 52 70 54 54 59 58 71 66 55 56];
Y=[40 33 35 37 33 36 32 36 35 33 41 35 37 31 40 41 34 33 34 37 ];
scatter(X,Y,'ro');
Thank you for everyone's help. Also remembered we can use hist3:
x={0:0.38/4:0.38}; % # How many bins in x direction
y={0:0.65/7:0.65}; % # How many bins in y direction
ncount=hist3([X Y],'Edges',[x y]);
pcolor(ncount./sum(sum(ncount)));
colorbar
Anyone know why edges in hist3 have to be cells?
This is basically a question about estimating the probability density function generating your data and then visualizing it in a good and meaningful way I'd say. To that end, I would recommend using a more smooth estimate than the histogram, for instance Parzen windowing (a generalization of the histogram method).
In my code below, I have used your example dataset, and estimated the probability density in a grid set up by the range of your data. You here have 3 variables you need to adjust to use on your original data; Borders, Sigma and stepSize.
Border = 5;
Sigma = 5;
stepSize = 1;
X=[53 58 62 56 72 63 65 57 52 56 52 70 54 54 59 58 71 66 55 56];
Y=[40 33 35 37 33 36 32 36 35 33 41 35 37 31 40 41 34 33 34 37 ];
D = [X' Y'];
N = length(X);
Xrange = [min(X)-Border max(X)+Border];
Yrange = [min(Y)-Border max(Y)+Border];
%Setup coordinate grid
[XX YY] = meshgrid(Xrange(1):stepSize:Xrange(2), Yrange(1):stepSize:Yrange(2));
YY = flipud(YY);
%Parzen parameters and function handle
pf1 = #(C1,C2) (1/N)*(1/((2*pi)*Sigma^2)).*...
exp(-( (C1(1)-C2(1))^2+ (C1(2)-C2(2))^2)/(2*Sigma^2));
PPDF1 = zeros(size(XX));
%Populate coordinate surface
[R C] = size(PPDF1);
NN = length(D);
for c=1:C
for r=1:R
for d=1:N
PPDF1(r,c) = PPDF1(r,c) + ...
pf1([XX(1,c) YY(r,1)],[D(d,1) D(d,2)]);
end
end
end
%Normalize data
m1 = max(PPDF1(:));
PPDF1 = PPDF1 / m1;
%Set up visualization
set(0,'defaulttextinterpreter','latex','DefaultAxesFontSize',20)
fig = figure(1);clf
stem3(D(:,1),D(:,2),zeros(N,1),'b.');
hold on;
%Add PDF estimates to figure
s1 = surfc(XX,YY,PPDF1);shading interp;alpha(s1,'color');
sub1=gca;
view(2)
axis([Xrange(1) Xrange(2) Yrange(1) Yrange(2)])
Note, this visualization is actually 3-dimensional:
See this 4 minute video on the mathworks site:
http://blogs.mathworks.com/videos/2010/01/22/advanced-making-a-2d-or-3d-histogram-to-visualize-data-density/
I believe this should provide very close to exactly the functionality you require.
I would divide the area the plot covers into a grid and then count the number of points in each square of the grid. Here's an example of how that could be done.
% Get random data with high density
X=randn(1e4,1);
Y=randn(1e4,1);
Xmin=min(X);
Xmax=max(X);
Ymin=min(Y);
Ymax=max(Y);
% guess of grid size, could be divided into nx and ny
n=floor((length(X))^0.25);
% Create x and y-axis
x=linspace(Xmin,Xmax,n);
y=linspace(Ymin,Ymax,n);
dx=x(2)-x(1);
dy=y(2)-y(1);
griddata=zeros(n);
for i=1:length(X)
% Calculate which bin the point is positioned in
indexX=floor((X(i)-Xmin)/dx)+1;
indexY=floor((Y(i)-Ymin)/dy)+1;
griddata(indexX,indexY)=griddata(indexX,indexY)+1;
end
contourf(x,y,griddata)
Edit: The video in the answer by Marm0t uses the same technique but probably explains it in a better way.