Related
I have created some MatLab code that plots a plane wave using two different expressions that give the same plane wave. The first expression is in Cartesian coordinates and works fine. However, the second expression is in polar coordinates and when I calculate the plane wave in this case, the plot is distorted. Both plots should look the same. So what am I doing wrong in transforming to/from polar coordinates?
function Plot_Plane_wave()
clc
clear all
close all
%% Step 0. Input paramaters and derived parameters.
alpha = 0*pi/4; % angle of incidence
k = 1; % wavenumber
wavelength = 2*pi/k; % wavelength
%% Step 1. Define various equivalent versions of the incident wave.
f_u_inc_1 = #(alpha,x,y) exp(1i*k*(x*cos(alpha)+y*sin(alpha)));
f_u_inc_2 = #(alpha,r,theta) exp(1i*k*r*cos(theta-alpha));
%% Step 2. Evaluate the incident wave on a grid.
% Grid for field
gridMax = 10;
gridN = 2^3;
g1 = linspace(-gridMax, gridMax, gridN);
g2 = g1;
[x,y] = meshgrid(g1, g2);
[theta,r] = cart2pol(x,y);
u_inc_1 = f_u_inc_1(alpha,x,y);
u_inc_2 = 0*x;
for ir=1:gridN
rVal = r(ir);
for itheta=1:gridN
thetaVal = theta(itheta);
u_inc_2(ir,itheta) = f_u_inc_2(alpha,rVal,thetaVal);
end
end
%% Step 3. Plot the incident wave.
figure(1);
subplot(2,2,1)
imagesc(g1(1,:), g1(1,:), real(u_inc_1));
hGCA = gca; set(hGCA, 'YDir', 'normal');
subplot(2,2,2)
imagesc(g1(1,:), g1(1,:), real(u_inc_2));
hGCA = gca; set(hGCA, 'YDir', 'normal');
end
Your mistake is that your loop is only going through the first gridN values of r and theta. Instead you want to step through the indices of ix and iy and pull out the rVal and thetaVal of the matrices r and theta.
You can change your loop to
for ix=1:gridN
for iy=1:gridN
rVal = r(ix,iy); % Was equivalent to r(ix) outside inner loop
thetaVal = theta(ix,iy); % Was equivalent to theta(iy)
u_inc_2(ix,iy) = f_u_inc_2(alpha,rVal,thetaVal);
end
end
which gives the expected graphs.
Alternatively you can simplify your code by feeding matrices in to your inline functions. To do this you would have to use an elementwise product .* instead of a matrix multiplication * in f_u_inc_2:
alpha = 0*pi/4;
k = 1;
wavelength = 2*pi/k;
f_1 = #(alpha,x,y) exp(1i*k*(x*cos(alpha)+y*sin(alpha)));
f_2 = #(alpha,r,theta) exp(1i*k*r.*cos(theta-alpha));
% Change v
f_old = #(alpha,r,theta) exp(1i*k*r *cos(theta-alpha));
gridMax = 10;
gridN = 2^3;
[x,y] = meshgrid(linspace(-gridMax, gridMax, gridN));
[theta,r] = cart2pol(x,y);
subplot(1,3,1)
contourf(x,y,real(f_1(alpha,x,y)));
title 'Cartesian'
subplot(1,3,2)
contourf(x,y,real(f_2(alpha,r,theta)));
title 'Polar'
subplot(1,3,3)
contourf(x,y,real(f_old(alpha,r,theta)));
title 'Wrong'
I have about four series of data on a Matlab plot, two of them are quite close and can only be differentiated with a zoom. How do I depict the zoomed part within the existing plot for the viewer. I have checked similar posts but the answers seem very unclear.
I look for something like this:
Here is a suggestion how to do this with MATLAB. It may need some fine tuning, but it will give you the result:
function pan = zoomin(ax,areaToMagnify,panPosition)
% AX is a handle to the axes to magnify
% AREATOMAGNIFY is the area to magnify, given by a 4-element vector that defines the
% lower-left and upper-right corners of a rectangle [x1 y1 x2 y2]
% PANPOSTION is the position of the magnifying pan in the figure, defined by
% the normalized units of the figure [x y w h]
%
fig = ax.Parent;
pan = copyobj(ax,fig);
pan.Position = panPosition;
pan.XLim = areaToMagnify([1 3]);
pan.YLim = areaToMagnify([2 4]);
pan.XTick = [];
pan.YTick = [];
rectangle(ax,'Position',...
[areaToMagnify(1:2) areaToMagnify(3:4)-areaToMagnify(1:2)])
xy = ax2annot(ax,areaToMagnify([1 4;3 2]));
annotation(fig,'line',[xy(1,1) panPosition(1)],...
[xy(1,2) panPosition(2)+panPosition(4)],'Color','k')
annotation(fig,'line',[xy(2,1) panPosition(1)+panPosition(3)],...
[xy(2,2) panPosition(2)],'Color','k')
end
function anxy = ax2annot(ax,xy)
% This function converts the axis unites to the figure normalized unites
% AX is a handle to the figure
% XY is a n-by-2 matrix, where the first column is the x values and the
% second is the y values
% ANXY is a matrix in the same size of XY, but with all the values
% converted to normalized units
pos = ax.Position;
% white area * ((value - axis min) / axis length) + gray area
normx = pos(3)*((xy(:,1)-ax.XLim(1))./range(ax.XLim))+ pos(1);
normy = pos(4)*((xy(:,2)-ax.YLim(1))./range(ax.YLim))+ pos(2);
anxy = [normx normy];
end
Note that the units of areaToMagnify are like the axis units, while the units of panPosition are between 0 to 1, like the position property in MATLAB.
Here is an example:
x = -5:0.1:5;
subplot(3,3,[4 5 7 8])
plot(x,cos(x-2),x,sin(x),x,-x-0.5,x,0.1.*x+0.1)
ax = gca;
area = [-0.4 -0.4 0.25 0.25];
inlarge = subplot(3,3,3);
panpos = inlarge.Position;
delete(inlarge);
inlarge = zoomin(ax,area,panpos);
title(inlarge,'Zoom in')
I have a data file which has got 3 columns one for position on x axis, the other one in time and the third one is temperature.
So, I interpolated the temperatures throughout my x and time to obtain a continuous interpolating polynomial handle using scatteredInterpolant.
Then I created a mesh over all my x and time values and obtained the value of interpolated polynomial over all these values.
And then I plotted the contour plot over all these interpolated values.
But I am seeing a bit strange behavior over here. As you could see in the figure my x values vary from 10 to some 1300. So if I keep these x values I see the blue region everywhere. But when I reduce this range to 200-1300 I still see the same blue region everywhere. And even if I change it to any other value the entire blue region as shown in the figure still remains.
So my problem is this, I want to have white region above the top boundary of my contour which you could see is somewhere around 1200 and a similar white region below the trailing tail of the contour on the x axis which is somewhere around may be 200 or so.
But I want to keep the blue region in that triangular zone at which the contour stops because there is material there at x=400-1200 at different time scales specified on the time axis i.e. the x axis.
P.S.: Just for clarity the y-axis is x values, the x-axis is time values and the contour corresponds to temperature on the z-axis obtained by interpolating the x and time using scatteredInterpolant function in matlab.
This is the script which I am using:
clear all; close all; clc;
load temperature.txt;
time = temperature(:,1); % This column contains the time
x = temperature(:,2); % This column contains the x values.
temperature_system = temperature(:,3); % This column contains the temperatures.
pos = temperature_system < prctile(temperature_system,41.967695);
time(pos) = [];
x(pos) = [];
temperature_system(pos) = [];
pos = (temperature_system > prctile(temperature_system,97));
time(pos) = [];
x(pos) = [];
temperature_system(pos) = [];
X1 = [time x];
F = scatteredInterpolant(X1,temperature_system);
x1 = linspace(min(x),max(x),100);
x2 = linspace(min(time),max(time),100);
[X,Y] = meshgrid(x2,x1);
Z = F(X,Y);
% plot3(x1,x2,F(x1,x2));
f1 = figure(1);
set(f1,'renderer','zbuffer');
%surf(X,Y,Z);
%ezcontourf(F)
[C,h] = contourf(X,Y,Z);
shading flat;
colormap(jet);
q = colorbar;
% cmap = colormap;
% cmap(1,:) = [1,1,1];
% colormap(cmap);
This is my figure without any modification:
And this is my picture if I remove the blue region with white region.
Please note the triangular zone at which the graph starts which is white now and was blue earlier, I want to keep this but how can I do that?
I think this is what your looking for. Please let me know if it's not. I just said if the temperature is out of range for all time at a point or all space in an instant, ignore it.
function StackOverflow
%Setting up variables, since I don't have the data
x = 1300*rand(1500, 1);
t = 45*rand(size(x));
T = 3000*exp(-((x - 650).^2/(2*(650/3)^2)) - ((t - 22.5).^2/(2*(22.5/3)^2)));
%Some criteria for ignoring below
TLow = 500;
%Create the interpolant on a regular grid
F = scatteredInterpolant([t, x], T);
xr = linspace(min(x),max(x),100);
tr = linspace(min(t),max(t),100);
[tr,xr] = meshgrid(tr,xr);
Tr = F(tr,xr);
%Is the data below the criteria for all points in space at a specific time
emptyTime = all(Tr < TLow,1);
%Is the data below the criteria for all time at a point in space
emptySpace = all(Tr < TLow, 2);
%If there is no data set it to nan
[emptyTime, emptySpace] = meshgrid(emptyTime, emptySpace);
Tr(emptyTime | emptySpace) = nan;
%Do plotting stuff
f1 = figure(1);
set(f1,'renderer','zbuffer');
[C,h] = contourf(tr,xr,Tr);
shading flat;
colormap(jet);
q = colorbar;
end
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
I wanna to plot a graph as the below:
And this one:
I was doing something like this:
cc=hsv(ns);
hold on;
for nk=1:ns
figure(4); hold on;
h=plot(M1(nk,:),':','color',cc(nk,:));
set(h,'linewidth',2)
end
How can I do it?
For the first plot you just need to use plot and text plus some tweaking. If you want the legend in two columns, have a look at columnlegend in the Matlab File Exchange.
% generate some data
days = (1:250);
M1 = (days'*[0.06,-0.03,0.02,-0.04,0.05,-0.05,0.01])';
M1 = M1 + 0.5*randn(size(M1));
years = 2002+(1:size(M1,1));
ns = size(M1,1);
% prepare plot
figure(4); hold on;
cc = hsv(ns);
% plot all prices
for nk = 1:ns
ph = plot(days,M1(nk,:),'Color',cc(nk,:));
set(ph,'LineWidth',2);
end
% plot texts
for i = 1:4
h = text(250/8+(i-1)*250/4,18,['Q',num2str(i)]);
set(h,'FontSize',13,'HorizontalAlignment','center');
end
% plot vertical lines and the horizontal line
plot([250,250]'*(0:4)/4,[-21,21],'k-.');
plot([-10,250+10],[0,0],'k-.');
% set limits
set(gca,'XLim',[-10,250+10]);
set(gca,'YLim',[-21,21]);
% set labels and legend
xlabel('Day of Trading');
ylabel('Normalized Price');
lh = legend(cellstr(num2str(years')),'Location','SouthWest');
set(lh,'FontSize',8);
% tweak appearance
set(gca,'YTick',-20:10:20);
set(gca,'FontSize',13);
set(gca,'GridLineStyle',':');
grid on;
box on;
This is the result:
The second plot is very similar to the first one. For the confidence interval you can use fill. Because the entries in the legend have a different order as the order of plotting them, we store the handles and give it as the first argument to legend.
% generate some data
rng(2);
days = (1:250);
realised_Q1 = (1:62)*0.04+0.5*randn(1,62);
realised_Q234 = realised_Q1(end)+(1:189)*0.03+0.5*randn(1,189);
forecast_Q234 = realised_Q1(end)-3*sin((1:189)/40);
confidence_up = forecast_Q234+(1-exp(-(0:188)/10));
confidence_down = forecast_Q234-(1-exp(-(0:188)/10));
% prepare plot
figure; hold on;
ph = zeros(4,1);
% plot confidence interval
ph(4) = fill([days(62:250),fliplr(days(62:250))],...
[confidence_up,fliplr(confidence_down)],...
[0.85,0.85,1],'EdgeColor','none');
% plot realized Q1
ph(1) = plot(days(1:62),realised_Q1,'r','LineWidth',2);
% plot realized Q2 Q3 Q4 and forecast Q2 Q3 Q4
ph(2) = plot(days(62:250),realised_Q234,'k','LineWidth',2);
ph(3) = plot(days(62:250),forecast_Q234,'b','LineWidth',2);
% plot texts
for i = 1:4
h = text(250/8+(i-1)*250/4,13,['Q',num2str(i)]);
set(h,'FontSize',13,'HorizontalAlignment','center');
end
% plot vertical lines and the horizontal line
plot([250,250]'*(0:4)/4,[-21,21],'k-.');
plot([-10,250+10],[0,0],'k-.');
% set limits
set(gca,'XLim',[-10,250+10]);
set(gca,'YLim',[-6,16]);
% set labels and legend
xlabel('Day of Trading');
ylabel('Normalized Price');
lh = legend(ph,'Realized Q1 (2011)','Realized Q2 Q3 Q4 (2011)',...
'Forecast Q2 Q3 Q4 (2011)','Confidence',...
'Location','SouthWest');
set(lh,'FontSize',8);
% tweak appearance
set(gca,'YTick',-5:5:15);
set(gca,'FontSize',13);
set(gca,'GridLineStyle',':');
grid on;
box on;
This is the result: