Plot heat conduction temperature at various radii with Matlab - matlab

I have an array in Matlab that is updated for every time step: each row corresponds to a time and each column represents a temperature at a certain radius from the center. It would also be handy if a color gradient could be applied to the plot using the meshgrid and contourf commands. So far, this is the Matlab code that I have, but I am not sure how to get the temperature into the plot and animate the change in temperature.
Tinf = 200; % ambient temperature
% where r1 = radius1, r2 = radius2, etc.
% t = time
% rows = time
% columns = radius
% r1 r2 r3 r4 r5
T = [98 105 110 118 128; % t=1
109 110 117 124 134; % t=2
110 118 120 130 144]; % t=3
r = 0.08; % radius of circle
rx = -r:0.01:r;
ry = r:-0.01:-r;
[x_coor, y_coor] = meshgrid(rx, ry);
radius = sqrt(x_coor.^2+y_coor.^2);
figure(1)
contourf(radius,'edgecolor','none')
I am trying to create a circular plot in Matlab that would show the temperature (color) at each radius and animate that temperature (change color) as it increases or decreases with time.
An example of such a plot at a certain time would be:
So column 1 in the T array corresponds to node 1 in the picture, column 2 corresponds to node 2, etc. Thus at time = 0 then node1 = 98, node2 = 105, node3 = 110, node4 = 118, node5 = 128; at time = 1 then node1 = 109, node2 = 110, node3 = 117, node4 = 124, node5 = 134; and so on.
Any suggestions to accomplish such a plot would be very helpful.

Same as #Magla's nice answer but draws a single surface (not an overlay) allowing interpolation
T = [98 105 110 118 128;
109 110 117 124 134;
114 118 120 130 138];
Rmax = 30;
[x,y,z] = sphere(100);
x=x*Rmax;
y=y*Rmax;
rxy2 = x.^2+y.^2;
r = [0 10 20 30];
r2 = r.^2;
figure('Color', 'w');
for ind_t = 1:size(T,1)
for ii = 1:length(r2)-1
ir_find = find(rxy2<=r2(ii+1) & rxy2>r2(ii));
z(ir_find) = T(ind_t,ii);
end
hax = axes('Position',[0 0 1 1]);
h = surf(x,y,z) % sphere centered at origin
shading interp
set(h, 'EdgeColor', 'None');
view(0,90);
axis equal;
set(hax, 'Visible', 'Off', 'CLim', [min(T(:)) max(T(:))]);
pause(0.5);
end
edit
Rewrote to use meshgrid and to use the particular radii etc of interest. Make sure to adjust r_res to a value you find adequate.
T = [98 105 110 118 128;
109 110 117 124 134;
114 118 120 130 138];
%---------------------------------------
r = 0.08; % radius of circle
r_res = 0.0005;
rx = -r:r_res:r;
ry = rx;
[x, y] = meshgrid(rx, ry);
rxy2 = x.^2+y.^2;
z=ones(size(rxy2))*NaN;
%---------------------------------------
Nshells = size(T,2);
r = [0:1/Nshells:1]*r;
r2 = r.^2;
figure('Color', 'w');
colormap hot
for ind_t = 1:size(T,1)
for ii = 1:Nshells
ir_find = find(rxy2<=r2(ii+1) & rxy2>r2(ii));
z(ir_find) = T(ind_t,ii);
end
hax = axes('Position',[0 0 1 1]);
h = surf(x,y,z) % sphere centered at origin
shading interp
set(h, 'EdgeColor', 'None');
view(0,90);
axis equal;
set(hax, 'Visible', 'Off', 'CLim', [min(T(:)) max(T(:))]);
pause(0.5);
end

Here is a solution that makes use of sphere. sphere generates the matrices x and y that are multiply by a decreasing radius r, and matrix z that is reduced to a single value (a sphere becomes a disk). z is multiplied by the temperature and disks are plotted on top of each other. Colors depend on the min and max of the whole input matrix. Animation is done with pause.
T = [98 105 110 118 128;
109 110 117 124 134;
114 118 120 130 138];
[x,y,z] = sphere(100);
r = [50 40 30 20 10];
figure('Color', 'w');
for ind_t = 1:size(T,1)
hax = axes('Position',[0 0 1 1]);
for ii = 1:length(r)
h = surf(x*r(ii),y*r(ii),z*0+T(ind_t,ii)) % sphere centered at origin
set(h, 'EdgeColor', 'None');
hold on;
end
view(0,90);
axis equal;
set(hax, 'Visible', 'Off', 'CLim', [min(T(:)) max(T(:))]);
pause(0.5);
end
This gives

Related

Curve fitting for non-linear data

I am trying to fit some data using lsqcurvefit in MATLAB but I am fairly new to this area.
xdata1 = [0 60 660 1250];
ydata1 = [0 18 23 31];
In the image below, the red line is the fit I want to achieve.
How can I achieve this fit?
How about polyfit() ?
Code here:
close all % be careful with following two lines
clear all
x = [0 60 660 1250];
y = [0 18 23 31];
p = polyfit(x,y,3);
xx = linspace(x(1), x(end), 100);
yy = polyval(p,xx);
plot(x,y,'o'); hold on; plot(xx,yy)

Adding axis to MATLAB figure

I have a polar plot that has colored contours. I cannot figure out how to add my axis. The code is below:
close all
data1 = xlsread('C:\Users\Desktop\practice.xlsx','theta');
data2 = xlsread('C:\Users\Desktop\practice.xlsx','r');
data3 = xlsread('C:\Users\Desktop\practice.xlsx'','z');
t = data1(1,:);
r = data2(:,1);
z = data3(:,:);
figure(1)
title('Displacement')
polarcont(r,t,z)
myColorMap = colormap;
myColorMap(1,:) = [1 1 1];
colormap(myColorMap);
colorbar;
caxis([0 25]);
beta = 0.9;
brighten(beta)
From here I cannot figure out how to plot my axes. For instance at theta=0, I would like [100], etc. Whenever I try what usually works,
thetaticks([0 15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 240 255 270 285 300 315 330 345])
rticks([100 200 300])
rticklabels({'100 eV','200 eV','300 eV'})
ax = gca;
ax.ThetaAxis.TickLabelInterpreter = 'latex';
ax.ThetaTickLabel = {'[100]','','','[101]','','','[001]','','','[$\overline{1}$01]','','','[$\overline{1}$00]','','','[$\overline{1}$0$\overline{1}$]','','','[00$\overline{1}$]','','','[10$\overline{1}$]','','','[$\overline{1}$0$\overline{1}$]'};
I just get riddled with errors involving trying to use polar axes on a cartesian chart. I can plot circles below which can give me the different r mag, but seems kind of a silly way to do it to me: (below)
plotting_circle(0,0,100);
plotting_circle(0,0,200)
plotting_circle(0,0,300)
plotting_circle(0,0,400)
axis equal
axis off

How to create a colormap based on value?

I have two vectors as follows:
x = 0:5:50;
sir_dB = [50 20 10 5 2 0 -5 -10 -20 -20 -20]
Where x denotes the distance on the x-axis and sir_dB the SNR. For this, I need to generate a color map for a grid of 50 x 60m something similar to this:
based on the value of sir_dB.
I tried the following:
sir_dB = [50 20 10 5 2 0 -5 -10 -20 -20 -20];
xrange = 0:50;
yrange = -30:30;
% create candidate set
[X, Y] = ndgrid(xrange, yrange); % grid of points with a spacing of 1.
candidate_set = [X(:), Y(:)];
test_pt = [0 30];
radius = 5;
% find which of these are within the radius of selected point:
idx = rangesearch(candidate_set, test_pt, radius );
neighborhood = candidate_set(idx{1}, :);
Once I have the neighbors at a radius of 5m, I need to color that part of the grid based on the sir_dB value for a corresponding x value.
I need to have the plot in such a way that for all values of sir_dB greater than 15, the grid should be colored green, yellow for y greater than 0 and red for y greater than -20.
Could someone provide me inputs of how to do this best?
Im not sure exactly what you want, but this should get you started with contourf. I increased the granularity of xrange and yrange to make the radius more smooth but you can change it back if you want.
x = 0:5:50;
sir_dB = [50 20 10 5 2 0 -5 -10 -20 -20 -20];
xrange = 0:0.1:50;
yrange = -30:0.1:30;
% create candidate set
[X, Y] = ndgrid(xrange, yrange); % grid of points with a spacing of 1.
candidate_set = [X(:), Y(:)];
test_pt = [0 30];
r = sqrt((test_pt(1)-X(:)).^2 + (test_pt(2)-Y(:)).^2);
idx = r>5;
snr = nan(size(X));
snr(idx) = interp1(x,sir_dB,X(idx),'linear');
% Some red, yellow, green colors
cmap = [0.8500 0.3250 0.0980;
0.9290 0.6940 0.1250;
0 0.7470 0.1245];
figure();
colormap(cmap);
contourf(X,Y,snr,[-20,0,15],'LineStyle','none');
Plotting the the contour plot alongside the original sir_dB we see that it lines up (assuming you want linear interpolation). If you don't want linear interpolation use 'prev' or 'next' for the interp1 method.
figure();
colormap(cmap);
subplot(2,1,1);
contourf(X,Y,snr,[-20,0,15],'LineStyle','none');
subplot(2,1,2);
plot([0,50],[-20,-20],'-r',[0,50],[0,0],'-y',[0,50],[15,15],'-g',x,sir_dB);
Here is another suggestion, to use imagesc for that. I nothed the changes in the code below with % ->:
x = 0:5:50;
sir_dB = [50 20 10 5 2 0 -5 -10 -20 -20 -20];
xrange = 0:50;
yrange = -30:30;
% create candidate set
[X, Y] = ndgrid(xrange, yrange); % grid of points with a spacing of 1.
% -> create a map for plotting
Signal_map = nan(size(Y));
candidate_set = [X(:), Y(:)];
test_pt = [10 20];
radius = 35;
% find which of these are within the radius of selected point:
idx = rangesearch(candidate_set,test_pt,radius);
neighborhood = candidate_set(idx{1}, :);
% -> calculate the distance form the test point:
D = pdist2(test_pt,neighborhood);
% -> convert the values to SNR color:
x_level = sum(x<D.',2);
x_level(x_level==0)=1;
ColorCode = sir_dB(x_level);
% -> apply the values to the map:
Signal_map(idx{1}) = ColorCode;
% -> plot the map:
imagesc(xrange,yrange,rot90(Signal_map,2))
axis xy
% -> apply custom color map for g-y-r:
cmap = [1 1 1 % white
1 0 0 % red
1 1 0 % yellow
0 1 0];% green
colormap(repelem(cmap,[1 20 15 35],1))
c = colorbar;
% -> scale the colorbar axis:
caxis([-21 50]);
c.Limits = [-20 50];
c.Label.String = 'SNR';
The result:

Matlab - creating an automatically animation transition for a line

I have the following picture:
and I want to create a continuous transition. The blue line (-20deg-start) goes until become like (22deg - original), and then goes until become like (60deg-stop).
the code to generate this lines is:
>> clear all
>> x=[0 11 20 34];
>> y=[2 8 17 32];
>> z=[9 20 29 43];
>> v=[16 23 32 43];
>> w=[15 26 35 49];
>> t=[30 40 47 55];
>> figure
>> hold on
>> plot(t,x, t,y, t,z, t,v, t,w)
Is it possible with the help of Matlab?
Thanks!
The following example shows how to do a linear transition between two curves, provided they are both defined on the same set of x values.
x = linspace(0,1,200); %// x values
y1 = log(1+x); %// y values of line 1
y2 = 1-x.^2; %// y values of line 2
c1 = [1 0 0]; %// red
c2 = [0 0 1]; %// blue
plot(x, y1, ':', 'color', c1); %// plot first line
hold on
plot(x, y2, ':', 'color', c2); %// plot second line
tt = linspace(0,1,100); %// define time axis, between 0 and 1. Adjust "100" for smoothness
h = plot(x, y1, '-', 'color', c2); %// moving line. Initially coincides with line 1
for t = tt
y = y1*(1-t) + y2*t;
c = c1*(1-t) + c2*t;
set(h, 'YData', y, 'Color', c); %// update y values and color of moving line
pause(.02) %// adjust ".02" as needed
end
Yes you can (well from what I understand you wish to achieve). You can put all your data into 1 big array and loop through each row and display it, with a small pause between each set of data.
Example:
clear
clc
close all
clear all
x=[0 11 20 34];
y=[2 8 17 32];
z=[9 20 29 43];
v=[16 23 32 43];
w=[15 26 35 49];
t=[30 40 47 55];
%// Put everything in single array
AllArrays = [x;y;z;v;w];
figure
hold all
%// Loop through each rows
for k = 1:size(AllArrays,1)
plot(t,AllArrays(k,:))
%// Make a pause to see output
pause(.5)
end
Output:
Is this what you meant? Or maybe a smoother transition?

How do I reproduce this heart-shaped mesh in MATLAB?

I want to plot a heart shape wireframe as shown in the following image
(source):
I have tried to make it by using this MATLAB program:
n=100;
x=linspace(-3,3,n);
y=linspace(-3,3,n);
z=linspace(-3,3,n);
[X,Y,Z]=ndgrid(x,y,z);
F=((-(X.^2) .* (Z.^3) -(9/80).*(Y.^2).*(Z.^3)) + ((X.^2) + (9/4).* (Y.^2) + (Z.^2)-1).^3);
isosurface(F,0)
lighting phong
caxis
axis equal
colormap('flag');
view([55 34]);
But I didn't get the desired shape of framework as shown in the figure.
I have identified the problem: to create a wireframe we usually use the command mesh(). But this plotting facility only allow us to plot a function of two variables such as z=f(x,y). But my program makes use of three variables: F(x,y,z).
How can I solve the problem?
Here's my best attempt at reproducing the entire figure:
Generating the contoured heart mesh:
I used the contourc function to generate a series of contours in the x-y, x-z, and y-z planes. Notice that in the image you want to reproduce, the mesh lines on the back-facing side of the heart are not rendered. The quickest and easiest way I could think of to reproduce that aspect of the plot was to use isosurface to render a white surface just beneath the inside surface of the mesh, blocking the view of the back side.
Here's the code for the function heart:
function heart
% Initialize the volume data, figure, and axes:
[X,Y,Z] = meshgrid(linspace(-3,3,101));
F = -X.^2.*Z.^3-(9/80).*Y.^2.*Z.^3+(X.^2+(9/4).*Y.^2+Z.^2-1).^3;
hFigure = figure('Position',[200 200 400 400],'Color','w');
hAxes = axes('Parent',hFigure,'Units','pixels',...
'Position',[1 1 400 400],'NextPlot','add',...
'DataAspectRatio',[1 1 1],'Visible','off',...
'CameraViewAngle',10,...
'XLim',[32 70],'YLim',[39 63],'ZLim',[34 73]);
view([-39 30]);
% Create and plot contours in the y-z plane:
for iX = [35 38 41 45 48 51 54 57 61 64 67]
plane = reshape(F(:,iX,:),101,101);
cData = contourc(plane,[0 0]);
xData = iX.*ones(1,cData(2,1));
plot3(hAxes,xData,cData(2,2:end),cData(1,2:end),'k');
end
% Create and plot contours in the x-z plane:
for iY = [41 44 47 51 55 58 61]
plane = reshape(F(iY,:,:),101,101);
cData = contourc(plane,[0 0]);
yData = iY.*ones(1,cData(2,1));
plot3(hAxes,cData(2,2:end),yData,cData(1,2:end),'k');
end
% Create and plot contours in the x-y plane:
for iZ = [36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 69 71]
plane = F(:,:,iZ);
cData = contourc(plane,[0 0]);
startIndex = 1;
if size(cData,2) > (cData(2,1)+1)
startIndex = cData(2,1)+2;
zData = iZ.*ones(1,cData(2,1));
plot3(hAxes,cData(1,2:(startIndex-1)),...
cData(2,2:(startIndex-1)),zData,'k');
end
zData = iZ.*ones(1,cData(2,startIndex));
plot3(hAxes,cData(1,(startIndex+1):end),...
cData(2,(startIndex+1):end),zData,'k');
end
% Fill the inside of the mesh with an isosurface to
% block rendering of the back side of the heart:
p = patch(isosurface(F,-0.001));
set(p,'FaceColor','w','EdgeColor','none');
end
Putting the figure together:
To reproduce the entire figure I first generated the heart mesh using the heart function above, then added the other elements around it. I also used a few submissions from The MathWorks File Exchange:
arrow.m from Erik Johnson (to generate the arrows)
myaa.m from Anders Brun (to create a nice anti-aliased final image)
Here's the code for the function I_Heart_Math (which generates the above figure):
function I_Heart_Math
% Initialize heart plot and adjust figure and axes settings:
heart;
set(gcf,'Position',[200 200 700 300],'Name','Original image');
offset = get(gca,'CameraPosition')-get(gca,'CameraTarget');
offset = 35.*offset./norm(offset);
set(gca,'Position',[65 -9 300 300],'CameraViewAngle',6,...
'XLim',[21+offset(1) 70],'YLim',[16+offset(2) 63],...
'ZLim',[32 81+offset(3)]);
% Create the axes and labels, offsetting them in front of the
% heart to give the appearance they are passing through it:
arrowStarts = [81 51 51; 51 86 51; 51 51 32]+repmat(offset,3,1);
arrowEnds = [21 51 51; 51 16 51; 51 51 81]+repmat(offset,3,1);
arrow(arrowStarts,arrowEnds,5,40,40);
text('Position',[22 52 48]+offset,'String','x','FontSize',12);
text('Position',[50 17 49]+offset,'String','y','FontSize',12);
text('Position',[46.5 51 81.5]+offset,'String','z','FontSize',12);
% Create the equation text:
text('Position',[51 47 28],'FontName','Bookman','FontSize',8,...
'HorizontalAlignment','center',...
'String',{'(x^2+^9/_4y^2+z^2-1)^3-x^2z^3-^9/_{80}y^2z^3=0'; ...
'-3 \leq x,y,z \leq 3'});
% Create the large-type text:
hI = text('Position',[4 52 69.5],'String','I',...
'FontAngle','italic','FontName','Trebuchet MS',...
'FontSize',116,'FontWeight','bold');
hM = text('Position',[80.5 50 42.5],'String','Math',...
'FontAngle','italic','FontName','Trebuchet MS',...
'FontSize',116,'FontWeight','bold');
% Create an anti-aliased version of the figure too (the larger
% fonts need some adjustment to do this... not sure why):
set(hI,'Position',[4 52 68],'FontSize',86);
set(hM,'Position',[80.5 50 41],'FontSize',86);
myaa;
set(hI,'Position',[4 52 69.5],'FontSize',116);
set(hM,'Position',[80.5 50 42.5],'FontSize',116);
set(gcf,'Name','Anti-aliased image');
end
A very elegant solution is given by #gnovice. I though I extend it by adding the other elements to replicate the figure pointed by the OP. I also added some cool animations!
% volume data
[X,Y,Z] = meshgrid(linspace(-3,3,101));
F = -X.^2.*Z.^3 - (9/80).*Y.^2.*Z.^3 + (X.^2 + (9/4).*Y.^2 + Z.^2 - 1).^3;
% initialize figure
hFig = figure('Menubar','none', 'Color','w');
pos = get(hFig, 'Position');
set(hFig, 'Position', [pos(1)-0.15*pos(3) pos(2) 1.3*pos(3) pos(4)]);
% initialize axes
hAxes = axes('Parent',hFig, 'DataAspectRatio',[1 1 1], ...
'XLim',[30 120], 'YLim',[35 65], 'ZLim',[30 75]);
view(-39,30);
axis off
% Fill the inside of the mesh with an isosurface to
% block rendering of the back side of the heart
patch(isosurface(F,-1e-3), 'FaceColor','w', 'EdgeColor','none')
hidden on % hidden surface removal
% contours in the y-z plane
for iX = [35 38 41 45 48 51 54 57 61 64 67]
plane = reshape(F(:,iX,:), [101 101]);
cData = contourc(plane, [0 0]);
xData = iX.*ones(1,cData(2,1));
line(xData, cData(2,2:end), cData(1,2:end), ...
'Color','r', 'Parent',hAxes)
pause(.1)
end
% contours in the x-z plane
for iY = [41 44 47 51 55 58 61]
plane = reshape(F(iY,:,:), [101 101]);
cData = contourc(plane, [0 0]);
yData = iY.*ones(1,cData(2,1));
line(cData(2,2:end), yData, cData(1,2:end), ...
'Color','r', 'Parent',hAxes)
pause(.1)
end
% contours in the x-y plane
for iZ = [36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 69 71]
plane = F(:,:,iZ);
cData = contourc(plane, [0 0]);
startIndex = 1;
if size(cData,2) > (cData(2,1)+1)
startIndex = cData(2,1)+2;
zData = iZ.*ones(1,cData(2,1));
line(cData(1,2:(startIndex-1)), cData(2,2:(startIndex-1)), zData, ...
'Color','r', 'Parent',hAxes)
end
zData = iZ.*ones(1,cData(2,startIndex));
line(cData(1,(startIndex+1):end), cData(2,(startIndex+1):end), zData, ...
'Color','r', 'Parent',hAxes)
pause(.1)
end
% text
props = {'FontWeight','bold', 'FontAngle','italic', 'FontSize',100};
pause(.2)
text(7,50,70, 'I', props{:})
pause(.5)
text(80,50,43, 'Math', props{:})
pause(.2)
% xyz axes
line([20 80], [50 50], [52.5 52.5], 'Color','k')
line([50 50], [20 80], [52.5 52.5], 'Color','k')
line([50 50], [50 50], [30 80], 'Color','k')
text(20,50,50, 'x')
text(48,20,50, 'y')
text(45,50,80, 'z')
drawnow
% equation
props = {'FontSize',10, 'Interpreter','latex'};
text(20,65,30, '$(x^2+9/4y^2+z^2-1)^3 - x^2z^3-9/80y^2z^3=0$', props{:});
text(30,45,30, '$-3 \leq x,y,z \leq 3$', props{:});
drawnow
(The above GIF file was created using GETFRAME and IMWRITE).
This code plots the shaded surface:
% volume data
step = 0.05;
[X,Y,Z] = meshgrid(-3:step:3, -3:step:3, -3:step:3);
F = (-(X.^2).*(Z.^3)-(9/80).*(Y.^2).*(Z.^3))+((X.^2)+(9/4).*(Y.^2)+(Z.^2)-1).^3;
% shaded surface
isosurface(X,Y,Z,F,0)
lighting phong
axis equal
view(-39,30)
set(gcf, 'Color','w')
colormap flag
We could instead plot the wireframe only:
% volume data
step = 0.05;
[X,Y,Z] = meshgrid(-3:step:3, -3:step:3, -3:step:3);
F = (-(X.^2).*(Z.^3)-(9/80).*(Y.^2).*(Z.^3))+((X.^2)+(9/4).*(Y.^2)+(Z.^2)-1).^3;
% wireframe
patch(isosurface(X,Y,Z,F,0), 'FaceColor','w', 'EdgeColor','b')
daspect([1 1 1])
view(3)
axis tight equal
set(gcf, 'Color','w')