visually plotting a value going to infinity in matlab - matlab

I am trying to reproduce the Dirac Delta function:
my code:
x = -30:1:30;
y = zeros(1,numel(x)); %sets all values initially to zero
y(x==0)= inf; % the point corresponding to x=0 is set to inf
plot(x,y,'d')
axis([-40 40 0 inf])
My code produces:

You can do this with stem, specifying its 'Marker' as an up arrow...
% Open figure
figure;
% Blue stem plot at x=0, to y=75. Marker style is up arrow
stem(0, 75,'color','b','linewidth',2,'marker','^')
% Add infinity label at x=0, y = 82 = 75 + fontsize/2, where we plotted up to 75
text(0,82,'∞','FontSize',14)
% Set axes limits
xlim([-40,40])
ylim([0,90])
You can see the output plot here, but see the edit below for an improved version.
Note, of course you should choose a y value which is large relative to any other data on the plot. In this example I chose 75 to roughly match your desired example plot. MATLAB can't plot a value at inf because, well, where does infinity sit on the y axis?
Edit: You can indicate the y-axis is broken with additional '≈' characters as suggested by Marco in the comments. Combining xlim and ylim into one axis call, and changing the y-axis ticks to help indicate the axis break, we get this result:
stem(0, 80,'color','b','linewidth',2,'marker','^')
text([-42,0,38], [80,87,80], {'≈','∞','≈'}, 'Fontsize', 14)
axis([-40, 40, 0, 100])
yticks(0:20:60)

To show infinity, you should not set y to infinity. To do this, you can set y to a large value proportional to the axis values. For example if axis would be like [min_x max_x min_y max_y], you can set y(x==0) = max_y*10.
In your case you will have:
x = -30:1:30; min_x = min(x) - 10; max_x = max(x) + 10;
y = zeros(1,numel(x));
% compute values of y here
% ...
min_y = min(y) - 10; max_y = max(y) + 10;
y(x==0)= 10 * max_y;
plot(x,y,'d');
axis([min_x max_x min_y max_y]);

Use the tick property in Matlab plot as described below

Related

Creating a circle in a square grid

I try to solve the following 2D elliptic PDE electrostatic problem by fixing the Parallel plate Capacitors code. But I have problem to plot the circle region. How can I plot a circle region rather than the square?
% I use following two lines to label the 50V and 100V squares
% (but it should be two circles)
V(pp1-r_circle_small:pp1+r_circle_small,pp1-r_circle_small:pp1+r_circle_small) = 50;
V(pp2-r_circle_big:pp2+r_circle_big,pp2-r_circle_big:pp2+r_circle_big) = 100;
% Contour Display for electric potential
figure(1)
contour_range_V = -101:0.5:101;
contour(x,y,V,contour_range_V,'linewidth',0.5);
axis([min(x) max(x) min(y) max(y)]);
colorbar('location','eastoutside','fontsize',10);
xlabel('x-axis in meters','fontsize',10);
ylabel('y-axis in meters','fontsize',10);
title('Electric Potential distribution, V(x,y) in volts','fontsize',14);
h1=gca;
set(h1,'fontsize',10);
fh1 = figure(1);
set(fh1, 'color', 'white')
% Contour Display for electric field
figure(2)
contour_range_E = -20:0.05:20;
contour(x,y,E,contour_range_E,'linewidth',0.5);
axis([min(x) max(x) min(y) max(y)]);
colorbar('location','eastoutside','fontsize',10);
xlabel('x-axis in meters','fontsize',10);
ylabel('y-axis in meters','fontsize',10);
title('Electric field distribution, E (x,y) in V/m','fontsize',14);
h2=gca;
set(h2,'fontsize',10);
fh2 = figure(2);
set(fh2, 'color', 'white')
You're creating a square due to the way you're indexing (see this post on indexing). You've specified the rows to run from pp1-r_circle_small to pp1+r_circle_small and similar for the columns. Given that Swiss cheese is not an option, you're creating a complete square.
From geometry we know that all points within distance sqrt((X-X0)^2 - (Y-Y0)^2) < R from the centre of the circle at (X0,Y0) with radius R are within the circle, and the rest outside. This means that you can simply build a mask:
% Set up your grid
Xsize = 30; % Your case: 1
Ysize = 30; % Your case: 1
step = 1; % Amount of gridpoints; use 0.001 or something
% Build indexing grid for circle search, adapt as necessary
X = 0:step:Xsize;
Y = 0:step:Ysize;
[XX,YY] = meshgrid(X, Y);
V = zeros(numel(X), numel(Y));
% Repeat the below for both circles
R = 10; % Radius of your circle; your case 0.1 and 0.15
X0 = 11; % X coordinate of the circle's origin; your case 0.3 and 0.7
Y0 = 15; % Y coordinate of the circle's origin; your case 0.3 and 0.7
% Logical check to see whether a point is inside or outside
mask = sqrt( (XX - X0).^2 + (YY - Y0).^2) < R;
V(mask) = 50; % Give your circle the desired value
imagesc(V) % Just to show you the result
axis equal % Use equal axis to have no image distortion
mask is a logical matrix containing 1 where points are within your circle and 0 where points are outside. You can then use this mask to logically index your potential grid V to set it to the desired value.
Note: This will, obviously, not create a perfect circle, given you cannot plot a perfect circle on a square grid. The finer the grid, the more circle-like your "circle" will be. This shows the result with step = 0.01
Note 2: You'll need to tweek your definition of X, Y, X0, Y0 and R to match your values.

build my own function that does the same work as 'semilogx' MATLAB function

How can I build my own function in Matlab that does the same work as the Matlab built-in function 'semilogx'?
Example: in this example both fig.1 and fig.2 plot x as a log scale but the values on the x-axis of fig.1 are not correct. So the question is "how can I make the values in fig.1 same as the values in fig.2 without using semilogx?"
x = 0:1000;
y = 2*x;
figure(1), plot(log10(x), y)
figure(2), semilogx(x,y)
I guess in my example above: in Fig.1 x limit is between [0,3] and in Fig.2 x limit is between [0,1000]. What I understand is that x limit should be [0:1000] but when we use log scale this would change to [0,3] so the semilogx function only maps the [0,3] limit to [0,1000]
Basically you have to reconstruct the x-axis tick mark locations and the corresponding tick labels on a log-scaled grid:
% Some data
x = 1:1000;
y = cumsum(rand(size(x)));
% For comparison
subplot(311); plot(log10(x), y)
subplot(312); semilogx(x,y)
% Simulated semilogx plot
subplot(313); plot(log10(x), y)
ax = gca; % Get a handle to the axis for tick modifications
% Compute tick mark locations in log10 scale
logxmax = ceil(log10(x(end)));
ticks = log10(1:9);
ticks = ticks' + (0:logxmax-1);
ticks = [ticks(:); logxmax];
% Set tick marks and labels
ax.XTick = ticks;
ax.XLim = [0 logxmax];
% Reset tick labels
ax.XTickLabel(:) = ''; % clear all tick labels
I = 1+9*(0:logxmax); % Tick labels for 10^n locations
S = arrayfun(#(x)'10^{'+string(x)+'}', (0:logxmax), 'UniformOutput', false);
ax.XTickLabel(I) = S;

How to turn y axis of histogram to show percentage ranging from 0 to 1

I want to change the y axis of the histogram to show percentages ranging from 0 to 1. this is what I've tried, but it doesn't seem to be working.
myTolerance=1e-12; % in erg units.
nbins=50;
for j=1:ntM/100:ntM
H = histfit(Wkinet(abs(Wkinet(:,j))>myTolerance, j) * erg2eV, nbins);
%Select from column j all rows in column j whose absolute values are
%greater than the tolerance.
H(1).delete; %%Remove bins, only keep the fit.
set(gca, 'YScale', 'log');
set(gca, 'XScale', 'log'); % Make logarithmic X
yt = get(gca, 'YTick');
set(gca, 'YTick', yt, 'YTickLabel',
yt/numel(Wkinet(abs(Wkinet(:,j))>myTolerance)))
pause;
end
This is what is currently looks like:
This is what I want:
Just to simplify the discussion below, the line
H = histfit(Wkinet(abs(Wkinet(:,j))>myTolerance, j) * erg2eV, nbins);
is equivalent to
data = Wkinet(abs(Wkinet(:,j))>myTolerance, j) * erg2eV;
H = histfit(data, nbins);
This means below we'll assume data is a vector.
histfit computes and plots a histogram though histogram, then fits a function to it through fitdist. Since you don't want to plot the histogram itself, just stick to fitdist:
pd = fitdist(data,'Normal'); % this is the default distribution used in `histfit`, is it correct?
x = linspace(min(data),max(data),200); % 200 points in the graph, you might want to change this?
y = pdf(pd,x);
plot(x,y);
Now it's simple to normalize the plot however we want. For example set the first element to 1:
pd = fitdist(data,'Normal');
x = linspace(min(data),max(data),200);
y = pdf(pd,x);
y = y/y(1); % <<< Normalize
plot(x,y);
You can set limits on your y-axis using
ylim([1e-3 1]) %lower limit is nonzero since it's plotted on log scale
or
set(gca, 'ylim', [1e-3 1])

matlab: moving circle along a graph and axis equal

Hello and pardon me if my english is a bit rusty. I'm trying to create a circle that moves along a parametric function (coordinates are stored in vectors). I have written a function for drawing the circle and I know that you can use the axis equal command in matlab in order to create a circle shape and avoid an ellipse. My problem is that when I do this the figure window becomes very wide relative to the plotted graph. Any input is appreciated.
MAIN CODE:
t = linspace(0,3);
x = 30*cos(pi/4)/2*(1-exp(-0.5*t));
y = (30*sin(pi/4)/2 + 9.81/0.5^2)*(1-exp(0.5*t)) - 9.81*t/0.5;
for i = 1:length(t)
plot(x,y)
axis equal
hold on
cirkel(x(i),y(i),1,1,'r') % argument #3 is the radius #4 is 1 for fill
hold off
pause(0.01)
end
CIRCLE CODE:
function cirkel(x,y,r,f,c)
angle = linspace(0, 2*pi, 360);
xp = x + r*cos(angle);
yp = y + r*sin(angle);
plot(x,y)
if f == 1 && nargin == 5
fill(xp,yp,c)
end
When you call axis equal it makes one unit of the x axis be the same size as one unit of the y axis. You are seeing what you are because your y values span a much larger range than the x values.
One way to deal with this would be to query the aspect ratio and x/y limits of the current axes as shown in the second part of this answer. However, an easier approach is rather than using fill to plot your circle, you could instead use scatter with a circular marker which will be circular regardless of the aspect ratio of your axes.
t = linspace(0,3);
x = 30*cos(pi/4)/2*(1-exp(-0.5*t));
y = (30*sin(pi/4)/2 + 9.81/0.5^2)*(1-exp(0.5*t)) - 9.81*t/0.5;
% Plot the entire curve
hplot = plot(x, y);
hold on;
% Create a scatter plot where the area of the marker is 50. Store the handle to the plot
% in the variable hscatter so we can update the position inside of the loop
hscatter = scatter(x(1), y(1), 50, 'r', 'MarkerFaceColor', 'r');
for k = 1:length(t)
% Update the location of the scatter plot
set(hscatter, 'XData', x(k), ... % Set the X Position of the circle to x(k)
'YData', y(k)) % Set the Y Position of the circle to y(k)
% Refresh the plot
drawnow
end
As a side note, it is best to update existing plot objects rather than creating new ones.
If you want the small dot to appear circular, and you want to have a reasonable domain (x-axis extent), try this:
function cirkel(x,y,r,f,c)
angle = linspace(0, 2*pi, 360);
xp = x + 0.04*r*cos(angle); %% adding scale factor of 0.04 to make it appear circular
yp = y + r*sin(angle);
plot(x,y)
if f == 1 && nargin == 5
fill(xp,yp,c)
end
Note the addition of the scale factor in the computation of xp. If you want to automate this, you can add another parameter to cirkel(), let's call it s, that contains the scale factor. You can calculate the scale factor in your script by computing the ratio of the range to the domain (y extent divided by x extent).

How to plot a rectangular in MATLAB

It is necessary for me that plot a rectangular in MATLAB by contour. But when I plot this, the figure is like square and no rectangular.
In fact the length of X axis and Y axis are true, but figure is not rectangular.
How could I find a rectangular figure?
Once before I needed to plot a n eliptical by countour and it was like circle, by setting axes([xmin xmax ymin ymax]) this problem was solved but know this command do not work.
Here is my code u0,x,y are 3 vectors of length nx*ny. and nx and ny are the number of points in x axis and y axis.
figure
for i=1:ny
z(i,:)=u0((i-1)*nx+1:i*nx);
x1(i,:)=x((i-1)*nx+1:i*nx);
y1(i,:)=y((i-1)*nx+1:i*nx);
end;
cMap = [0.45 0.6 0.65;1 1 1]; % [green;yellow] on rgb-color
colormap(cMap);
axis equal
contourf(x1,y1,z,'LineColor','none')
colorbar
Let 's=0:0.1:0.2' and 'x=repmat(s,1,ny)' and 'd=0:0.1:1', 'y=repmat(d,1,nx)'
'u0=x+y'
I think the problem is the size of the vector you are using. Check out this example:
x = linspace(0,2,20);
y = linspace(0,1,10);
z = meshgrid(x,y);
contourf(x,y,z,20);
axis equal
it gives the following result:
Now if we check the sizes:
>> size(x)
ans =
1 20
>> size(y)
ans =
1 10
>> size(z)
ans =
10 20
if the size of x vector is equal to the size of the y vector it gives you a square obviously! in your case first check the size of x1, y1, z just before using the contourf an make sure that you are using axis equal after that.