Related
I am trying to plot the DC component of the Fourier Series together with the harmonics in the first panel. But the first panel only outputs the harmonics. Please help me in solving this one. Below is my code and output plot.
n = 30;
x = (0:300)/100;
xx = 2*x;
ao = 1/2; %DC component
f = ones(1,301)*ao;
for i = 1:2:n
bn = 2/pi/i;
bnx = bn*sin(2*pi*i*x);
f = f + bnx;
subplot(1,2,1)
plot(xx,ao) %Plotting of DC component
hold on
plot(xx,bnx)
hold on
subplot(1,2,2)
plot(xx,f)
hold off
end
The problem is the line
plot(xx,ao) %Plotting of DC component
Here xx is a vector and ao is a number. From the documentation, in this case the plot function plots discrete points; and these are not even visible because no marker has been specified.
To obtain a horizontal line of height ao, you need to replace the above by the following, so that both inputs to plot are vectors:
plot(xx,repmat(ao,size(xx)))
In addition, it would be better to move this line of code, together with subplot(1,2,1) and hold on, before the loop, to plot the DC component only once:
n = 30;
x = (0:300)/100;
xx = 2*x;
ao = 1/2; %DC component
f = ones(1,301)*ao;
subplot(1,2,1)
plot(xx,repmat(ao,size(xx))) %Plotting of DC component
hold on
for i = 1:2:n
bn = 2/pi/i;
bnx = bn*sin(2*pi*i*x);
f = f + bnx;
subplot(1,2,1)
plot(xx,bnx)
subplot(1,2,2)
plot(xx,f)
hold off
end
I am trying to average my CFD data (which is in the form of a scalar N x M x P array; N corresponds to Y, M to x, and P to z) over a subset of time steps. I've tried to simplify the description of my desired averaging process below.
Rotate the grid at each time step by a specified angle (this is because the flow has a coherent structure that rotates and changes shape/size at each time step and I want to overlap them and find a time averaged form of the structure that takes into account the change of shape/size over time)
Drawing a sphere centered on the original unrotated grid
Identifying the grid points from all the rotated grids that lie within the sphere
Identify the indices of the grid points in each rotated grid
Use the indices to find the scalar data at the rotated grid points within the sphere
Take an average of the values within the sphere
Put that new averaged value at the location on the unrotated grid
I have a code that seems to do what I want correctly, but it takes far too long to finish the calculations. I would like to make it run faster, and I am open to changing the code if necessary. Below is version of my code that works with a smaller version of the data.
x = -5:5; % x - position data
y = -2:.5:5; % y - position data
z = -5:5; % z - position data
% my grid is much bigger actually
[X,Y,Z] = meshgrid(x,y,z); % mesh for plotting data
dX = diff(x)'; dX(end+1) = dX(end); % x grid intervals
dY = diff(y)'; dY(end+1) = dY(end); % y grid intervals
dZ = diff(z)'; dZ(end+1) = dZ(end); % z grid intervals
TestPoints = combvec(x,y,z)'; % you need the Matlab Neural Network Toolbox to run this
dXYZ = combvec(dX',dY',dZ')';
% TestPoints is the unrotated grid
M = length(x); % size of grid x - direction
N = length(y); % size of grid y - direction
P = length(z); % size of grid z - direction
D = randi([-10,10],N,M,P,3); % placeholder for data for 3 time steps (I have more than 3, this is a subset)
D2{3,M*N*P} = [];
PosAll{3,2} = [];
[xSph,ySph,zSph] = sphere(50);
c = 0.01; % 1 cm
nu = 8e-6; % 8 cSt
s = 3*c; % span for Aspect Ratio 3
r_g = s/sqrt(3);
U_g = 110*nu/c; % velocity for Reynolds number 110
Omega = U_g/r_g; % angular velocity
T = (2*pi)/Omega; % period
dt = 40*T/1920; % time interval
DeltaRotAngle = ((2*pi)/T)*dt; % angle interval
timesteps = 121:123; % time steps 121, 122, and 123
for ti=timesteps
tj = find(ti==timesteps);
Theta = ti*DeltaRotAngle;
Rotate = [cos(Theta),0,sin(Theta);...
0,1,0;...
-sin(Theta),0,cos(Theta)];
PosAll{tj,1} = (Rotate*TestPoints')';
end
for i=1:M*N*P
aa = TestPoints(i,1);
bb = TestPoints(i,2);
cc = TestPoints(i,3);
rs = 0.8*sqrt(dXYZ(i,1)^2 + dXYZ(i,2)^2 + dXYZ(i,3)^2);
handles.H = figure;
hs = surf(xSph*rs+aa,ySph*rs+bb,zSph*rs+cc);
[Fs,Vs,~] = surf2patch(hs,'triangle');
close(handles.H)
for ti=timesteps
tj = find(timesteps==ti);
f = inpolyhedron(Fs,Vs,PosAll{tj,1},'FlipNormals',false);
TestPointsR_ti = PosAll{tj,1};
PointsInSphere = TestPointsR_ti(f,:);
p1 = [aa,bb,cc];
p2 = [PointsInSphere(:,1),...
PointsInSphere(:,2),...
PointsInSphere(:,3)];
w = 1./sqrt(sum(...
(p2-repmat(p1,size(PointsInSphere,1),1))...
.^2,2));
D_ti = reshape(D(:,:,:,tj),M*N*P,1);
D2{tj,i} = [D_ti(f),w];
end
end
D3{M*N*P,1} = [];
for i=1:M*N*P
D3{i} = vertcat(D2{:,i});
end
D4 = zeros(M*N*P,1);
for i=1:M*N*P
D4(i) = sum(D3{i}(:,1).*D3{i}(:,2))/...
sum(D3{i}(:,2));
end
D_ta = reshape(D4,N,M,P);
I expect to get an N x M x P array where each index is the weighted average of all the points covering all of the time steps at that specific position in the unrotated grid. As you can see this is exactly what I get. The major problem however is the length of time it takes to do so when I use the larger set of my 'real' data. The code above takes only a couple minutes to run, but when M = 120, N = 24, and P = 120, and the number of time steps is 24 this can take much longer. Based on my estimates it would take approximately 25+ days to finish the entire calculation.
Nevermind, I can help you with the math. What you are trying to do here is find things inside a sphere. You have a well-defined sphere so this makes things easy. Just find the distance of all points from the center point. No need to plot or use inpolyhedron. Note line 66 where I modify the points by the center point of the sphere, compute the distance of these points, and compare to the radius of the sphere.
% x = -5:2:5; % x - position data
x = linspace(-5,5,120);
% y = -2:5; % y - position data
y = linspace(-2,5,24);
% z = -5:2:5; % z - position data
z = linspace(-5,5,120);
% my grid is much bigger actually
[X,Y,Z] = meshgrid(x,y,z); % mesh for plotting data
dX = diff(x)'; dX(end+1) = dX(end); % x grid intervals
dY = diff(y)'; dY(end+1) = dY(end); % y grid intervals
dZ = diff(z)'; dZ(end+1) = dZ(end); % z grid intervals
TestPoints = combvec(x,y,z)'; % you need the Matlab Neural Network Toolbox to run this
dXYZ = combvec(dX',dY',dZ')';
% TestPoints is the unrotated grid
M = length(x); % size of grid x - direction
N = length(y); % size of grid y - direction
P = length(z); % size of grid z - direction
D = randi([-10,10],N,M,P,3); % placeholder for data for 3 time steps (I have more than 3, this is a subset)
D2{3,M*N*P} = [];
PosAll{3,2} = [];
[xSph,ySph,zSph] = sphere(50);
c = 0.01; % 1 cm
nu = 8e-6; % 8 cSt
s = 3*c; % span for Aspect Ratio 3
r_g = s/sqrt(3);
U_g = 110*nu/c; % velocity for Reynolds number 110
Omega = U_g/r_g; % angular velocity
T = (2*pi)/Omega; % period
dt = 40*T/1920; % time interval
DeltaRotAngle = ((2*pi)/T)*dt; % angle interval
timesteps = 121:123; % time steps 121, 122, and 123
for ti=timesteps
tj = find(ti==timesteps);
Theta = ti*DeltaRotAngle;
Rotate = [cos(Theta),0,sin(Theta);...
0,1,0;...
-sin(Theta),0,cos(Theta)];
PosAll{tj,1} = (Rotate*TestPoints')';
end
tic
for i=1:M*N*P
aa = TestPoints(i,1);
bb = TestPoints(i,2);
cc = TestPoints(i,3);
rs = 0.8*sqrt(dXYZ(i,1)^2 + dXYZ(i,2)^2 + dXYZ(i,3)^2);
% handles.H = figure;
% hs = surf(xSph*rs+aa,ySph*rs+bb,zSph*rs+cc);
% [Fs,Vs,~] = surf2patch(hs,'triangle');
% close(handles.H)
for ti=timesteps
tj = find(timesteps==ti);
% f = inpolyhedron(Fs,Vs,PosAll{tj,1},'FlipNormals',false);
f = sqrt(sum((PosAll{tj,1}-[aa,bb,cc]).^2,2))<rs;
TestPointsR_ti = PosAll{tj,1};
PointsInSphere = TestPointsR_ti(f,:);
p1 = [aa,bb,cc];
p2 = [PointsInSphere(:,1),...
PointsInSphere(:,2),...
PointsInSphere(:,3)];
w = 1./sqrt(sum(...
(p2-repmat(p1,size(PointsInSphere,1),1))...
.^2,2));
D_ti = reshape(D(:,:,:,tj),M*N*P,1);
D2{tj,i} = [D_ti(f),w];
end
if ~mod(i,10)
toc
end
end
D3{M*N*P,1} = [];
for i=1:M*N*P
D3{i} = vertcat(D2{:,i});
end
D4 = zeros(M*N*P,1);
for i=1:M*N*P
D4(i) = sum(D3{i}(:,1).*D3{i}(:,2))/...
sum(D3{i}(:,2));
end
D_ta = reshape(D4,N,M,P);
In terms of runtime, on my computer, the old code takes 57 hours to run. The new code takes 2 hours. At this point, the main calculation is the distance so I doubt you'll get much better.
I have an axisymmetric flow with m x n grid points in r and z direction and I want to plot the temperature that is stored in a matrix with size mxn in a 3D cylindrical plot as visualized in the link below (My reputation is not high enough to include it as a picture).
I have managed to plot it in 2D (r,z plane) using contour but I would like to add the theta plane for visualization. How can I do this?
You can roll your own with multiple calls to surface().
Key idea is: for each surface: (1) theta=theta1, (2) theta=theta2, (3) z=zmax, (4) z=0, (5) r=rmax, generate a 3D mesh (xx,yy,zz) and the temperature map on that mesh. So you have to think about how to construct each surface mesh.
Edit: completed code is now provided. All magic number and fake data are put at (almost) the top of the code so it's easy to convert it into a general purpose Matlab function. Good luck!
% I have adjusted the range values to show the curved cylinder wall
% display a variable temperature
r = 0:0.1:2.6; % you can also try r = 0:0.1:3.0
z = 0:0.1:10; % you can also try z = 0:0.1:15;
[rr, zz] = meshgrid(r,z);
% fake temperature data
temp = 100 + (10* (3-rr).^0.6) .* (1-((zz - 7.5)/7.5).^6) ;
% visualize in 2D
figure(1);
clf;
imagesc(r,z,temp);
colorbar;
% set cut planes angles
theta1 = 0;
theta2 = pi*135/180;
nt = 40; % angle resolution
figure(2);
clf;
xx1 = rr * cos(theta1);
yy1 = rr * sin(theta1);
h1 = surface(xx1,yy1,zz,temp,'EdgeColor', 'none');
xx2 = rr * cos(theta2);
yy2 = rr * sin(theta2);
h2 = surface(xx2,yy2,zz,temp,'EdgeColor', 'none');
% polar meshgrid for the top end-cap
t3 = linspace(theta1, (theta2 - 2*pi), nt);
[rr3, tt3] = meshgrid(r,t3);
xx3 = rr3 .* cos(tt3);
yy3 = rr3 .* sin(tt3);
zz3 = ones(size(rr3)) * max(z);
temp3 = zeros(size(rr3));
for k = 1:length(r)
temp3(:,k) = temp(end,k);
end
h3 = surface(xx3,yy3,zz3,temp3,'EdgeColor', 'none');
% polar meshgrid for the bottom end-cap
zz4 = ones(size(rr3)) * min(z);
temp4 = zeros(size(rr3));
for k = 1:length(r)
temp4(:,k) = temp(1,k);
end
h4 = surface(xx3,yy3,zz4,temp4,'EdgeColor', 'none');
% generate a curved meshgrid
[tt5, zz5] = meshgrid(t3,z);
xx5 = r(end) * cos(tt5);
yy5 = r(end) * sin(tt5);
temp5 = zeros(size(xx5));
for k = 1:length(z)
temp5(k,:) = temp(k,end);
end
h5 = surface(xx5, yy5, zz5,temp5,'EdgeColor', 'none');
axis equal
colorbar
view(125,25); % viewing angles
I need to extract the isoline coordinates of a 4D variable from a 3D surface defined using a triangulated mesh in MATLAB. I need the isoline coordinates to be a ordered in such a manner that if they were followed in order they would trace the path i.e. the order of the points a 3D printer would follow.
I have found a function that can calculate the coordinates of these isolines (see Isoline function here) but the problem is this function does not consider the isolines to be joined in the correct order and is instead a series of 2 points separated by a Nan value. This makes this function only suitable for visualisation purposes and not the path to follow.
Here is a MWE of the problem of a simplified problem, the surface I'm applying it too is much more complex and I cannot share it. Where x, y and z are nodes, with TRI providing the element connectivity list and v is the variable of which I want the isolines extracted from and is not equal to z.
If anyone has any idea on either.....
A function to extract isoline values in the correct order for a 3D tri mesh.
How to sort the data given by the function Isoline so that they are in the correct order.
.... it would be very much appreciated.
Here is the MWE,
% Create coordinates
[x y] = meshgrid( -10:0.5:10, -10:0.5:10 );
z = (x.^2 + y.^2)/20; % Z height
v = x+y; % 4th dimension value
% Reshape coordinates into list to be converted to tri mesh
x = reshape(x,[],1); y = reshape(y,[],1); z = reshape(z,[],1); v = reshape(v,[],1);
TRI = delaunay(x,y); % Convertion to a tri mesh
% This function calculates the isoline coordinates
[xTows, yTows, zTows] = IsoLine( {TRI,[x, y, z]}, v, -18:2:18);
% Plotting
figure(1); clf(1)
subplot(1,2,1)
trisurf(TRI,x,y,z,v)
hold on
for i = 1:size(xTows,1)
plot3( xTows{i,1}, yTows{i,1}, zTows{i,1}, '-k')
end
hold off
shading interp
xlabel('x'); ylabel('y'); zlabel('z'); title('Isolines'), axis equal
%% This section is solely to show that the isolines are not in order
for i = 1:size(xTows,1)
% Arranging data into colums and getting rid of Nans that appear
xb = xTows{i,1}; yb = yTows{i,1}; zb = zTows{i,1};
xb = reshape(xb, 3, [])'; xb(:,3) = [];
yb = reshape(yb, 3, [])'; yb(:,3) = [];
zb = reshape(zb, 3, [])'; zb(:,3) = [];
subplot(1,2,2)
trisurf(TRI,x,y,z,v)
shading interp
view(2)
xlabel('x'); ylabel('y'); zlabel('z'); title('Plotting Isolines in Order')
axis equal; axis tight; hold on
for i = 1:size(xb,1)
plot3( [xb(i,1) xb(i,2)], [yb(i,1) yb(i,2)], [zb(i,1) zb(i,2)], '-k')
drawnow
end
end
and here is the function Isoline, which I have slightly adpated.
function [xTows, yTows, zTows] = IsoLine(Surf,F,V,Col)
if length(Surf)==3 % convert mesh to triangulation
P = [Surf{1}(:) Surf{2}(:) Surf{3}(:)];
Surf{1}(end,:) = 1i;
Surf{1}(:,end) = 1i;
i = find(~imag(Surf{1}(:)));
n = size(Surf{1},1);
T = [i i+1 i+n; i+1 i+n+1 i+n];
else
T = Surf{1};
P = Surf{2};
end
f = F(T(:));
if nargin==2
V = linspace(min(f),max(f),22);
V = V(2:end-1);
elseif numel(V)==1
V = linspace(min(f),max(f),V+2);
V = V(2:end-1);
end
if nargin<4
Col = 'k';
end
H = NaN + V(:);
q = [1:3 1:3];
% -------------------------------------------------------------------------
% Loop over iso-values ----------------------------------------------------
xTows = [];
yTows = [];
zTows = [];
for k = 1:numel(V)
R = {[],[]};
G = F(T) - V(k);
C = 1./(1-G./G(:,[2 3 1]));
f = unique(T(~isfinite(C))); % remove degeneracies by random perturbation
F(f) = F(f).*(1+1e-12*rand(size(F(f)))) + 1e-12*rand(size(F(f)));
G = F(T) - V(k);
C = 1./(1-G./G(:,[2 3 1]));
C(C<0|C>1) = -1;
% process active triangles
for i = 1:3
f = any(C>=0,2) & C(:,i)<0;
for j = i+1:i+2
w = C(f,q([j j j]));
R{j-i} = [R{j-i}; w.*P(T(f,q(j)),:)+(1-w).*P(T(f,q(j+1)),:)];
end
end
% define isoline
for i = 1:3
X{i} = [R{1}(:,i) R{2}(:,i) nan+R{1}(:,i)]';
% X{i} = [R{1}(:,i) R{2}(:,i)]'; % Changed by Matt
X{i} = X{i}(:)';
end
% plot isoline
if ~isempty(R{1})
% hold on
% H(k) = plot3(X{1},X{2},X{3},Col);
% Added by M.Thomas
xTows{k,1} = X{1};
yTows{k,1} = X{2};
zTows{k,1} = X{3};
end
end
What you will notice is that the isolines (xTows, yTows and zTows) are not in order there "jump around" when plotted sequentially. I need to sort the tows so that they give a smooth plot in order.
I'm doing Gaussian processes and I calculated a regression per year from a given matrix where each row represents a year , so the code is:
M1 = MainMatrix; %This is the given Matrix
ker =#(x,y) exp(-1013*(x-y)'*(x-y));
[ns, ms] = size(M1);
for N = 1:ns
x = M1(N,:);
C = zeros(ms,ms);
for i = 1:ms
for j = 1:ms
C(i,j)= ker(x(i),x(j));
end
end
u = randn(ms,1);
[A,S, B] = svd(C);
z = A*sqrt(S)*u; % z = A S^.5 u
And I wanna plotting each regression in a Graph 3D as the below:
I know that plot is a ribbon, but I have not idea how can I do that
The desired plot can be generated without the use of ribbon. Just use a surf-plot for all the prices and a fill3-plot for the plane at z=0. The boundaries of the plane are calculated from the actual limits of the figure. Therefore we need to set the limits before plotting the plane. Then just some adjustments are needed to generate almost the same appearance.
Here is the code:
% generate some data
days = (1:100)';
price = days*[0.18,-0.08,0.07,-0.10,0.12,-0.08,0.05];
price = price + 0.5*randn(size(price));
years = 2002+(1:size(price,2));
% prepare plot
width = 0.6;
X = ones(size(price,1),1)*0.5;
X = [-X,X]*width;
figure; hold on;
% plot all 'ribbons'
for i = 1:size(price,2)
h = surf([days,days],X+years(i),[price(:,i),price(:,i)]);
set(h,'MeshStyle','column');
end
% set axis limits
set(gca,'ZLim',[-20,20]);
% plot plane at z=0
limx = get(gca,'XLim');
limy = get(gca,'YLim');
fill3(reshape([limx;limx],1,[]),[flip(limy),limy],zeros(1,4),'g','FaceAlpha',0.2)
% set labels
xlabel('Day of trading')
ylabel('Year')
zlabel('Normalized Price')
% tweak appearance
set(gca,'YTick',years);
set(gca,'YDir','reverse');
view([-38,50])
colormap jet;
grid on;
%box on;
This is the result:
That's a ribbon plot with an additional surface at y=0 which can be drawn with fill3