contour plot in Plotly - contour

With Plotly, I want to plot the contour plot of Z(rho, theta), where rho is the radial and theta is the azimuth coordinates. My first step is to create a meshgrid of rho and theta and calculate the function Z at each grid. I then convert the rho-theta grid to X-Y Cartesian coordinates grid. The Surface plot and its z-projection contour in fig00 are based on X,Y,Z coordinates and are all correct. I have a problem when I want to plot only the contour in fig0.
go.Contour requires one-dimensional x,y coordinates that in Cartesian coordinates are no longer uniform. Moreover, using rho-theta arrays does not produce circular contours as is shown in fig0.
Would anyone be able to assist me with this?
Thank you very much.
'''
dia=9.6
rho = np.linspace(0, dia / 2, 20)
theta= np.linspace(0, 2 * np.pi, 20)
RR, P = np.meshgrid(rho, theta)
X, Y = RR * np.cos(P), RR * np.sin(P)
trace00 = go.Surface(x= X, y= Y, z= ZZ, colorscale=‘rainbow’)
layout00 = go.Layout(title=’ Tear Layer Map’)
fig00 = go.Figure(data=[trace00], layout=layout00)
fig00.update_traces(contours_z=dict(show=True, usecolormap=True,
highlightcolor=“limegreen”, project_z=True))
st.plotly_chart(fig00)
trace0 = go.Contour( x= RR[0,:], y= P[:,0], z= Z, connectgaps=True)
layout0 = go.Layout(margin=dict(l=0, r=0, b=0, t=0))
fig0 = go.Figure(data=[trace0], layout=layout0)
fig0.update_layout(polar_bargap=0)
st.plotly_chart(fig0)
'''

Related

How can I map this matrix into another coordinate system, so it can be added to a second matrix?

I am trying to solve a problem which I may struggle to describe, so will attempt to describe with the aid of the following picture (please bear with me!):
I have two matrices which are defined on different coordinate spaces (u,v) for matrix A and (x,y) for matrix B. They have different grid sizes and different numbers of pixels. My goal is to apply a scaling factor S to the matrix A, and then to simply add it to matrix B. (For context, this is an optical imaging problem, where matrix A is located at an object plane, matrix B is located at an image plane, and S is the magnification).
So, I would like to create a new matrix C which is the equivalent of A but brought into the new coordinates (x,y). Matrix C should have the same number of rows and columns as B.
A minimum example of A and B is shown below, where the red dashed lines on the right illustrate the effective physical regions occupied by matrix A's pixels:
This is produced by the following code:
%%% Inputs for matrix A %%%
M = 4; % num columns in matrix A
N = 4; % num rows in matrix A
du = 13; % horizontal size of a pixel in matrix A [mm]
dv = 13; % vertical size of a pixel in matrix A [mm]
%%% Set up matrix A %%%
Lu = (M-1)*du; % physical hor. coord. of centre of last pixel [mm]
Lv = (N-1)*dv; % physical ver. coord. of centre of last pixel [mm]
u = -Lu/2:du:Lu/2; % hor. coordinates for matrix A [mm]
v = -Lv/2:dv:Lv/2; % ver. coordinates for matrix A [mm]
A = zeros(N,M);
A(1,1) = 1; % Set a few values to 1 for testing
A(2,3) = 1;
A(3,4) = 1;
%%% Inputs for matrix B %%%
dx = 0.1; % grid step in matrix B [mm]
dy = 0.1; % grid step in matrix B [mm]
Lx = 6; % physical hor. coord. of centre of last pixel [mm]
Ly = 6; % physical ver. coord. of centre of last pixel [mm]
%%% Set up matrix B %%%
x = -Lx/2:dx:Lx/2;
y = -Ly/2:dy:Ly/2;
B = rand(length(y),length(x));
figure('color','w');
subplot(1,2,1);imagesc(u, v, A); axis equal tight;
subplot(1,2,2);imagesc(x, y, B); axis equal tight;
S = 1/20; % scale factor from matrix A's corrdinates to matrix B's
% C = ?
In this example, I have set the pixel size of matrix A to be 13mm, and the scaling factor to be 1/20. This means that in B's coordinates each pixel should be 13/20 = 0.65mm. This is bigger than the grid size dx=0.1mm, and so in this case the result should be that, after mapping, pixels should span multiple grid points. Any region outside the total extent of matrix A should be padded with zeros.
Is there a simple way (or built-in function) which would quickly generate matrix C in Matlab (ideally without using loops over each pixel, or interpolation)?
I can simply scale the coordinates, which matches the physical dimensions, but the matrices are still different number of rows and columns:
u_scaled = u*S;
v_scaled = v*S;
subplot(1,3,3);imagesc(u_scaled, v_scaled, A); axis equal tight;
You can use interp2 or griddedInterpolant:
C = interp2(u, v, A, x * 20, y.' * 20, 'nearest', 0);
With some modification better result can be produced:
AA = padarray(A, [1 1], 0);
uu = [-du+u(1) u u(end)+du];
vv = [-dv+v(1) v v(end)+dv];
C = interp2(uu, vv, AA, x * 20, y.' * 20, 'nearest', 0);

Outline (circumference) polygon extraction from contiguous patch of equal squares [duplicate]

If I have the coordinates of the points on the outline of an arbitrary 2D shape, how can I find the coordinates of points composing the outline of a stair step curve, which best represents the original outline, but only use a set of known coordinates (xi, i=1,...,n and yi, i=1,...,m). For example the original triangle is represented by the thick solid blue line. it's different from the matlab stairs function, if my understanding is correct.
matlab code will be nice, but in other language is also ok, algorithm is most important.Thanks.
I'll start by defining a set of sample data based on your plot. Assuming that the pixel centers are aligned at integer values (the convention MATLAB follows) and that the lower left corner is at (0.5, 0.5), here's the data we get:
vx = [1.5; 9.7; 3.7; 1.5]; % X values of triangle vertices
vy = [8.3; 6.0; 1.7; 8.3]; % Y values of triangle vertices
x = 1:10; % X pixel center coordinates
y = 1:9; % Y pixel center coordinates
Note that the vertex coordinates are ordered starting at the top left corner of the triangle and proceeding clockwise, repeating the first vertex at the end to close the polygon.
Getting the mask (the easy part):
There is an easy way to compute the dark gray mask if you have the Image Processing Toolbox: use poly2mask:
mask = poly2mask(vx, vy, numel(y), numel(x));
The algorithm this function uses is discussed here. However, if you'd like to use a pure MATLAB approach that requires no special toolboxes, you can use inpolygon instead:
[cx, cy] = meshgrid(x, y); % Generate a grid of x and y values
mask = inpolygon(cx, cy, vx, vy);
In this case, a pixel is included in the mask as long as its center point lies within the polygon. In this particular example these two approaches yield the same resulting mask, but they won't always due to the differences in their criteria for deciding if a pixel is included or not.
Getting the outline coordinates:
It's a little more involved to get the coordinates of the mask outline, ordered appropriately around the perimeter. To accomplish this, we can represent the mask as a series of vertices and triangular facets (using the triangulation function), then compute the free boundary (i.e. edges that are only present on one triangular facet):
% Create raw triangulation data:
[cx, cy] = meshgrid(x, y);
xTri = bsxfun(#plus, [0; 1; 1; 0], cx(mask).');
yTri = bsxfun(#plus, [0; 0; 1; 1], cy(mask).');
V = [xTri(:) yTri(:)];
F = reshape(bsxfun(#plus, [1; 2; 3; 1; 3; 4], 0:4:(4*nnz(mask)-4)), 3, []).';
% Trim triangulation data:
[V, ~, Vindex] = unique(V, 'rows');
V = V-0.5;
F = Vindex(F);
% Create triangulation and find free edge coordinates:
TR = triangulation(F, V);
freeEdges = freeBoundary(TR).';
xOutline = V(freeEdges(1, [1:end 1]), 1); % Ordered edge x coordinates
yOutline = V(freeEdges(1, [1:end 1]), 2); % Ordered edge y coordinates
And we can plot this like so:
imagesc(x, y, mask);
axis equal
set(gca, 'XLim', [min(x)-0.5 max(x)+0.5], ...
'YLim', [min(y)-0.5 max(y)+0.5], ...
'XTick', x, 'YTick', y, 'YDir', 'normal');
colormap([0.9 0.9 0.9; 0.6 0.6 0.6]);
hold on;
plot(xOutline, yOutline, 'b', 'LineWidth', 2);
plot(xOutline(1), yOutline(1), 'go', 'LineWidth', 2);
plot(vx, vy, 'r', 'LineWidth', 2);
The outline coordinates in xOutline and yOutline are ordered starting from the green circle going counter-clockwise around the mask region.
Seems you need any line rasterization algorithm (that gives coordinate of integer grid points approximating line segment).
Consider Bresenham algortihm or DDA one.

How to generate the stair step curve(outline) for any 2d shape(or curve)?

If I have the coordinates of the points on the outline of an arbitrary 2D shape, how can I find the coordinates of points composing the outline of a stair step curve, which best represents the original outline, but only use a set of known coordinates (xi, i=1,...,n and yi, i=1,...,m). For example the original triangle is represented by the thick solid blue line. it's different from the matlab stairs function, if my understanding is correct.
matlab code will be nice, but in other language is also ok, algorithm is most important.Thanks.
I'll start by defining a set of sample data based on your plot. Assuming that the pixel centers are aligned at integer values (the convention MATLAB follows) and that the lower left corner is at (0.5, 0.5), here's the data we get:
vx = [1.5; 9.7; 3.7; 1.5]; % X values of triangle vertices
vy = [8.3; 6.0; 1.7; 8.3]; % Y values of triangle vertices
x = 1:10; % X pixel center coordinates
y = 1:9; % Y pixel center coordinates
Note that the vertex coordinates are ordered starting at the top left corner of the triangle and proceeding clockwise, repeating the first vertex at the end to close the polygon.
Getting the mask (the easy part):
There is an easy way to compute the dark gray mask if you have the Image Processing Toolbox: use poly2mask:
mask = poly2mask(vx, vy, numel(y), numel(x));
The algorithm this function uses is discussed here. However, if you'd like to use a pure MATLAB approach that requires no special toolboxes, you can use inpolygon instead:
[cx, cy] = meshgrid(x, y); % Generate a grid of x and y values
mask = inpolygon(cx, cy, vx, vy);
In this case, a pixel is included in the mask as long as its center point lies within the polygon. In this particular example these two approaches yield the same resulting mask, but they won't always due to the differences in their criteria for deciding if a pixel is included or not.
Getting the outline coordinates:
It's a little more involved to get the coordinates of the mask outline, ordered appropriately around the perimeter. To accomplish this, we can represent the mask as a series of vertices and triangular facets (using the triangulation function), then compute the free boundary (i.e. edges that are only present on one triangular facet):
% Create raw triangulation data:
[cx, cy] = meshgrid(x, y);
xTri = bsxfun(#plus, [0; 1; 1; 0], cx(mask).');
yTri = bsxfun(#plus, [0; 0; 1; 1], cy(mask).');
V = [xTri(:) yTri(:)];
F = reshape(bsxfun(#plus, [1; 2; 3; 1; 3; 4], 0:4:(4*nnz(mask)-4)), 3, []).';
% Trim triangulation data:
[V, ~, Vindex] = unique(V, 'rows');
V = V-0.5;
F = Vindex(F);
% Create triangulation and find free edge coordinates:
TR = triangulation(F, V);
freeEdges = freeBoundary(TR).';
xOutline = V(freeEdges(1, [1:end 1]), 1); % Ordered edge x coordinates
yOutline = V(freeEdges(1, [1:end 1]), 2); % Ordered edge y coordinates
And we can plot this like so:
imagesc(x, y, mask);
axis equal
set(gca, 'XLim', [min(x)-0.5 max(x)+0.5], ...
'YLim', [min(y)-0.5 max(y)+0.5], ...
'XTick', x, 'YTick', y, 'YDir', 'normal');
colormap([0.9 0.9 0.9; 0.6 0.6 0.6]);
hold on;
plot(xOutline, yOutline, 'b', 'LineWidth', 2);
plot(xOutline(1), yOutline(1), 'go', 'LineWidth', 2);
plot(vx, vy, 'r', 'LineWidth', 2);
The outline coordinates in xOutline and yOutline are ordered starting from the green circle going counter-clockwise around the mask region.
Seems you need any line rasterization algorithm (that gives coordinate of integer grid points approximating line segment).
Consider Bresenham algortihm or DDA one.

How to determine a semi-sphere's point x-y-z coordinates?

I'm having serious problems solving a problem illustrated on the pic below.
Let's say we have 3 points in 3D space (blue dots), and the some center of the triangle based on them (red dot - point P). We also have a normal to this triangle, so that we know which semi-space we talking about.
I need to determine, what is the position on a point (red ??? point) that depends on two angles, both in range of 0-180 degrees. Doesnt matter how the alfa=0 and betha=0 angle is "anchored", it is only important to be able to scan the whole semi-sphere (of radius r).
http://i.stack.imgur.com/a1h1B.png
If anybody could help me, I'd be really thankful.
Kind regards,
Rav
From the drawing it looks as if the position of the point on the sphere is given by a form of spherical coordinates. Let r be the radius of the sphere; let alpha be given relative to the x-axis; and let beta be the angle relative to the x-y-plane. The Cartesian coordinates of the point on the sphere are:
x = r * cos(beta) * cos(alpha)
y = r * cos(beta) * sin(alpha)
z = r * sin(beta)
Edit
But for a general coordinate frame with axes (L, M, N) centered at (X, Y, Z) the coordinates are (as in dmuir's answer):
(x, y, z) =
(X, Y, Z)
+ r * cos(beta) * cos(alpha) * L
+ r * cos(beta) * sin(alpha) * M
+ r * sin(beta) * N
The axes L and N must be orthogonal and M = cross(N, L). alpha is given relative to L, and beta is given relative to the L-M plane. If you don't know how L is related to points of the triangle, then the question can't be answered.
You need to find two unit length orthogonal vectors L, M say, in the plane of the triangle as well as the the unit normal N. The points on the sphere are
r*cos(beta)*cos(alpha) * L + r*cos(beta)*sin(alpha)*M + r*sin(beta)*N

Algorithm: Calculate pseudo-random point inside an ellipse

For a simple particle system I'm making, I need to, given an ellipse with width and height, calculate a random point X, Y which lies in that ellipse.
Now I'm not the best at maths, so I wanted to ask here if anybody could point me in the right direction.
Maybe the right way is to choose a random float in the range of the width, take it for X and from it calculate the Y value?
Generate a random point inside a circle of radius 1. This can be done by taking a random angle phi in the interval [0, 2*pi) and a random value rho in the interval [0, 1) and compute
x = sqrt(rho) * cos(phi)
y = sqrt(rho) * sin(phi)
The square root in the formula ensures a uniform distribution inside the circle.
Scale x and y to the dimensions of the ellipse
x = x * width/2.0
y = y * height/2.0
Use rejection sampling: choose a random point in the rectangle around the ellipse. Test whether the point is inside the ellipse by checking the sign of (x-x0)^2/a^2+(y-y0)^2/b^2-1. Repeat if the point is not inside. (This assumes that the ellipse is aligned with the coordinate axes. A similar solution works in the general case but is more complicated, of course.)
It is possible to generate points within an ellipse without using rejection sampling too by carefully considering its definition in polar form. From wikipedia the polar form of an ellipse is given by
Intuitively speaking, we should sample polar angle θ more often where the radius is larger. Put more mathematically, our PDF for the random variable θ should be p(θ) dθ = dA / A, where dA is the area of a single segment at angle θ with width dθ. Using the equation for polar angle area dA = 1/2 r2 dθ and the area of an ellipse being π a b, then the PDF becomes
To randomly sample from this PDF, one direct method is the inverse CDF technique. This requires calculating the cumulative density function (CDF) and then inverting this function. Using Wolfram Alpha to get the indefinite integral, then inverting it gives inverse CDF of
where u runs between 0 and 1. So to sample a random angle θ, you just generate a uniform random number u between 0 and 1, and substitute it into this equation for the inverse CDF.
To get the random radius, the same technique that works for a circle can be used (see for example Generate a random point within a circle (uniformly)).
Here is some sample Python code which implements this algorithm:
import numpy
import matplotlib.pyplot as plt
import random
# Returns theta in [-pi/2, 3pi/2]
def generate_theta(a, b):
u = random.random() / 4.0
theta = numpy.arctan(b/a * numpy.tan(2*numpy.pi*u))
v = random.random()
if v < 0.25:
return theta
elif v < 0.5:
return numpy.pi - theta
elif v < 0.75:
return numpy.pi + theta
else:
return -theta
def radius(a, b, theta):
return a * b / numpy.sqrt((b*numpy.cos(theta))**2 + (a*numpy.sin(theta))**2)
def random_point(a, b):
random_theta = generate_theta(a, b)
max_radius = radius(a, b, random_theta)
random_radius = max_radius * numpy.sqrt(random.random())
return numpy.array([
random_radius * numpy.cos(random_theta),
random_radius * numpy.sin(random_theta)
])
a = 2
b = 1
points = numpy.array([random_point(a, b) for _ in range(2000)])
plt.scatter(points[:,0], points[:,1])
plt.show()
I know this is an old question, but I think none of the existing answers are good enough.
I was looking for a solution for exactly the same problem and got directed here by Google, found all the existing answers are not what I wanted, so I implemented my own solution entirely by myself, using information found here: https://en.wikipedia.org/wiki/Ellipse
So any point on the ellipse must satisfy that equation, how to make a point inside the ellipse?
Just scale a and b with two random numbers between 0 and 1.
I will post my code here, I just want to help.
import math
import matplotlib.pyplot as plt
import random
from matplotlib.patches import Ellipse
a = 4
b = a*math.tan(math.radians((random.random()+0.5)/2*45))
def random_point(a, b):
d = math.radians(random.random()*360)
return (a * math.cos(d) * random.random(), b * math.sin(d) * random.random())
points = [random_point(a, b) for i in range(360)]
x, y = zip(*points)
fig = plt.figure(frameon=False)
ax = fig.add_subplot(111)
ax.set_axis_off()
ax.add_patch(Ellipse((0, 0), 2*a, 2*b, edgecolor='k', fc='None', lw=2))
ax.scatter(x, y)
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
plt.axis('scaled')
plt.box(False)
ax = plt.gca()
ax.set_xlim([-a, a])
ax.set_ylim([-b, b])
plt.set_cmap('rainbow')
plt.show()

Resources