How to show more details in `seaborn.kdeplot()`? - seaborn

I have a scatter plot on the left-hand side below, where there are lots of data points, and the figure on the right are corresponding density plot using seaborn.kdeplot(). But unfortunately since the variance of the density is so large that kdeplot fails to capture many details in other low-density area (e.g. there is basically no information about the density distribution on the top right).
Does anyone have any ways to fix this issue?
Thanks!

You can use the n_levels parameter, i.e.
f, axes = plt.subplots(1, 3, figsize=(15, 5), sharex=True, sharey=True)
x, y = np.random.normal(0, 1, (2, 1000))
axes[0].scatter(x, y, s=5, c=".1")
sns.kdeplot(x, y, n_levels=10, ax=axes[1])
sns.kdeplot(x, y, n_levels=30, ax=axes[2])
f.tight_layout()

Related

Plotting contour circles in mathematica for a given function value and radius

I have an arbitrary function of f(x) with each discrete x value. The value of the function is circularly symmetrical. I want to plot those circles in mathematica using x as radius and values of f(x) as the height of this plot. Can you help me with that please? Also I don't know how to use lists of numbers as an input to plot discrete circles in 3D.
I tried
Plot3D[f*Exp[I*phi], {x, 0, 10}, {phi, 0, 2*Pi}]
or
ContourPlot[f*Exp[I*phi], {x, 0, 10}, {phi, 0, 2*Pi}]
Nothing shows up!
Try this
f[x_]:=x^2;
Show[
Map[(x=#;ParametricPlot3D[{x*Cos[phi],x*Sin[phi],f[x]},{phi,0,2Pi}])&,Range[1,10]],
PlotRange->All
]
where I arbitrarily picked an f[x] and used a list of {1,2,3,...10} for discrete x values. You could replace that Range[1,10] with something like {5,7,3/2,1.8} if you had a specific list of numbers that you wanted to use for x.
The Map function created a ParametricPlot3D for each of the discrete values of x and then the Show combined all those into a single plot.

Find highest possible x and y value of Points

I have measured points for fitting lines. The number of points I have measured in x-direction is the first value of the Point (e.g. X1) and the second value of this point are the measured points in y-direction.
X1(2,9)
X2(9,3)
X3(5,4)
X4(6,4)
This means,that e.g. in X3 I have measured 5 points in x-direction and in y-direction I have measured 4 points. With the points in x-direction I will fit a line in x-direction and with the points in y-direction, I will fit a line in y-direction. To get better results, more points in x direction and y-direction are better then less. For example it is better to choose X4, then X1, because in X1 I have in y-direction 9-Points, but in x-direction only 2 points, which will give me a poor result in x-direction. In X4 I have both: a high number of points in x and in y-direction. So I can be sure, that the lines will be good enough. So I want to find this X#, where I have a (the) high(est) number of points in x and in y direction
Have you tried checking your code? It seems like your X is on an ascending order and your Y is using the opposite order. Maybe like insert both x and y values on a variable then sort them with the same order as you want them to be.
You would need to write a function that ranks the 'fitness' of a point.
def fitness(point):
'''
ranks a point by the total number of points,
minus the difference between the number of x and y points.
uses total number of points as a secondary rank
'''
num_points = sum(point)
xydiff = max(point) - min(point)
return num_points - xydiff, num_points
The above function should be adjusted, depending on how you want to want to weight the points.
>>> points = [(2,9), (9,3), (5,4), (6,4)]
>>> sorted(points, key=fitness, reverse=True)
[(6, 4), (5, 4), (9, 3), (2, 9)]
>>> max(points, key=fitness) # the most fit point
(6, 4)

Marking a specific point on a graph in MATLAB

I guess this is a very basic question.
I have a graph which I created in MATLAB. This is a graph of Power (y-axis) versus Frequency (x-axis).
The range of my x-axis is from 0 to 1000. Now here is my problem. I want to draw a line from specific points on the x-axis to the graph. For example, for points 40, 400, 950.
By using set(gca, 'XTick', [40 400 950]); I am able to mark these particular points. But I want to make it more visible by drawing straight vertical lines from these points.
Any help will be greatly appreciated. Thank you.
Use plot with endpoints with the same x value and different y values. (and don't forget to use myaa to beautify the output).
x = 0:0.1:2*pi;
y = sin(x);
plot(x,y);
hold on;
plot([0.6 0.6], [-1 1], 'Color', [0.7 0.7 0.7], 'LineWidth', 2);
plot([3.6 3.6], [-1 1], 'Color', [0.7 0.7 0.7], 'LineWidth', 2);
If you do this often I would recommend you a great submission from the FileExchange:
hline and vline
Just do:
vline([40 400 950])
Read the function documentation, if you want the line to have different properties than default.
I typically do this using something like this (is powers is a row vector).
powers = randn(1,1000)+40;
plot([1;1]*[40 400 950], [[0 0 0]; [powers([40 400 950])]],'k-')

Evaluating/Fitting an ellipse from scattered points

Here is the deal. I have multiple points (X,Y) that form an 'ellipse like' shape.
I would like to evaluate/fit the 'best' ellipse possible and get its properties (a,b,F1,F2), or just the center of the ellipse.
Any ideas/leads would be appreciated.
Gilad.
There's a Matlab function fit_ellipse that can do the job. There's also this paper on methods for orthogonal distance fitting of ellipses. A web search for orthogonal ellipse fit will probably turn up a lot of other resources as well.
The ellipse fitting method proposed by:
Z. L. Szpak, W. Chojnacki, and A. van den Hengel.
Guaranteed ellipse fitting with a confidence region and an uncertainty measure for centre, axes, and orientation.
J. Math. Imaging Vision, 2015.
may be of interest to you. They provide estimates of both algebraic and geometric ellipse
parameters, together with covariance matrices that express the uncertainty of the parameter estimates.
They also provide a means of computing a planar 95% confidence region associated with the estimate
that allows one to visualise the uncertainty in the ellipse fit.
A pre-print version of the paper is available on the authors websites (http://cs.adelaide.edu.au/~wojtek/publicationsWC.html).
A MATLAB implementation of the method is also available for download:
https://sites.google.com/site/szpakz/source-code/guaranteed-ellipse-fitting-with-a-confidence-region-and-an-uncertainty-measure-for-centre-axes-and-orientation
I will explain how I would approach the problem. I would suggest a hill climbing approach. First compute the gravity center of the points as a start point and choose two values for a and b in some way(probably arbitrary positive values will do). You need to have a fit function and I would suggest it to return the number of points (close enough to)lying on a given ellipse:
int fit(x, y, a, b)
int res := 0
for point in points
if point_almost_on_ellipse(x, y, a, b, point)
res = res + 1
end_if
end_for
return res
Now start with some step. I would choose a big enough value to be sure the best center of the elipse will never be more then step away from the first point. Choosing such a big value is not necessary, but the slowest part of the algorithm is the time it takes to get close to the best center so bigger value is better, I think.
So now we have some initial point(x, y), some initial values of a and b and an initial step. The algorithm iteratively chooses the best of the neighbours of the current point if there is any neighbour better then it, or decrease step twice otherwise. Here by 'best' I mean using the fit function. And also a position is defined by four values (x, y, a, b) and it's neighbours are 8: (x+-step, y, a, b),(x, y+-step, a, b), (x, y, a+-step, b), (x, y, a, b+-step)(if results are not good enough you can add more neighbours by also going by diagonal - for instance (x+-step, y+-step, a, b) and so on). Here is how you do that
neighbours = [[-1, 0, 0, 0], [1, 0, 0, 0], [0, -1, 0, 0], [0, 1, 0, 0],
[0, 0, -1, 0], [0, 0, 1, 0], [0, 0, 0, -1], [0, 0, 0, 1]]
iterate (cx, cy, ca, cb, step)
current_fit = fit(cx, cy, ca, cb)
best_neighbour = []
best_fit = current_fit
for neighbour in neighbours
tx = cx + neighbour[0]*step
ty = cx + neighbour[1]*step
ta = ca + neighbour[2]*step
tb = cb + neighbour[3]*step
tfit = fit(tx, ty, ta, tb)
if (tfit > best_fit)
best_fit = tfit
best_neighbour = [tx,ty,ta,tb]
endif
end_for
if best_neighbour.size == 4
cx := best_neighbour[0]
cy := best_neighbour[1]
ca := best_neighbour[2]
cb := best_neighbour[3]
else
step = step * 0.5
end_if
And you continue iterating until the value of step is smaller then a given threshold(for instance 1e-6). I have written everything in pseudo code as I am not sure which language do you want to use.
It is not guaranteed that the answer found this way will be optimal but I am pretty sure it will be good enough approximation.
Here is an article about hill climbing.
I think that Wild Magic library contains a function for ellipse fitting. There is article with method decription
The problem is to define "best". What is best in your case? The ellipse with the smallest area which contains n% of pointS?
If you define "best" in terms of probability, you can simply use the covariance matrix of your points, and compute the error ellipse.
An error ellipse for this "multivariate Gaussian distribution" would then contain the points corresponding to whatever confidence interval you decide.
Many computing packages can compute the covariance, with its corresponding eigenvalues and eigenvectors. The angle of the ellipse is the angle between the x axis and the eigenvector corresponding to the largest eigenvalue. The semi-axes are the reciprocal of the eigenvalues.
If your routine returns everything normalized (which it should), then you can decide by what factor to multiply everything to obtain an alpha-confidence interval.

Mapping coordinates from plane given by normal vector to XY plane

So, I have this algorithm to calculate cross-section of 3D shape with plane given with normal vector.
However, my current problem is, that the cross-section is set of 3D points (all lying on that given plane) and to display it I need to map this coordinates to XY plane.
This works perfect if the plane normal is something like (0,0,c) - I just copy x and y coordinates discarding z.
And here is my question: Since I have no idea how to convert any other plain could anybody give me any hint as to what should I do now?
Your pane is defined by a normal vector
n=(xn,yn,zn)
For coordination transformation we need 2 base vectors and a zero point for the pane
Base vectors
We chose those "naturally" fitting to the x/y pane (see later for edge case):
b1=(1,0,zb1)
b2=(0,1,zb2)
And we want
b1 x b2 = n*c (c const scalar)
to make sure these two are really bases
Now solve this:
b1 x b2= (0*zb2-zb1*1,zb1*0-1*zb2,1*1-0*0) = (zb1,zb2,1)
zb1*c=xn
zb2*c=yn
1*c=zn
c=zn,
zb2=yn/c=yn/zn
zb1=xn/c=xn/zn
b1=(1,0,yn/zn)
b2=(0,1,xn/zn)
and normalize it
bv1=(1,0,yn/zn)*sqrt(1+(yn/zn*yn/zn))
bv2=(0,1,yn/zn)*sqrt(1+(xn/zn*xn/zn))
An edge case is, when zn=0: In this case the normal vector is parallel to the x/y pane and no natural base vectors exist, ind this case you have to chose base b1 and b2 vectors by an esthetic POV and go through the same solution process or just chose bv1 and bv2.
Zero point
you spoke of no anchor point for your pane in the OQ, but it is necessary to differentiate your pane from the infinite family of parallel panes.
If your anchor point is (0,0,0) this is a perfect anchor point for the coordinate transformation and your pane has
x*xn+y*yn+z*zn=0,
(y0,y0,z0)=(0,0,0)
If not, I assume you have an anchor point of (xa,ya,za) and your pane has
x*xn+y*yn+z*zn=d
with d const scalar. A natural fit would be the point of the pane, that is defined by normal projection of the original zero point onto the pane:
P0=(x0,y0,z0)
with
(x0, y0, z0) = c * (xn,yn,zn)
Solving this against
x*xn+y*yn+z*zn=d
gives
c*xn*xn+c*yn*yn+c*zn*zn=d
and
c=d/(xn*xn+yn*yn+zn*zn)
thus
P0=(x0,y0,z0)=c*(xn,yn,zn)
is found.
Final transformation
is achieved by representing every point of your pane (i.e. those points you want to show) as
P0+x'*bv1+y'*bv2
with x' and y' being the new coordinates. Since we know P0, bv1 and bv2 this is quite trivial. If we are not on the edge case, we have zeroes in bv1.y and bv2.x further reducing the problem.
x' and y' are the new coordinates you want.
I would like to add to Eugen's answer, a suggestion for the case where zn=0 extending his answer and also offer an alternative solution (which is similar).
In the case of zn=0, you can actually think of all the planes as points in a circle around the z-axis and the radius depends on the parameters of the plane.
Any vector orthogonal to the radius should be parallel to the plane, while the radius being the normal of the plane.
So in some way, the problem is reduced to a 2D-space.
The normal to the plane is (xn, yn, 0).
By using a technique to find orthogonal vectors in 2D, we get that a base vector could therefore be (-yn, xn, 0).
The second base vector is (0, 0, 1) which is just the normalized vector of their cross product. We can see that by developing the following expression:
corss_product((-yn, xn, 0), (xn, yn, 0)) =
(xn*0 - 0*yn, 0*xn - (-yn)*0, (-b)*b - a*a) =
(0, 0, -(xn^2 + yn^2)).
Which after normalizing and negating becomes (0, 0, 1).
From here, I suggest b1=normalize(-yn, xn, 0) and b2=(0, 0, 1).
Now, there's an even more general solution using this approach.
If you'll develop the dot product of (-yn, xn, 0) and (xn, yn, zn), you'll see that they are orthogonal for any zn while (-yn, xn, 0) also being part of the plane in question (when d=0). Thus, this actually works as long at least one of xn and yn is not zero (because otherwise (-yn, xn, 0) is actually just (0, 0, 0)).
Just to make sure it's clear, the second base vector is again their cross product, that is: b1=(-yn, xn, 0) and b2=cross_product(b1, n).
Well then, what about the case where both xn and yn are zero? In this case the plane is parallel to the xy plane. Now that's an easy one, just choose b1=(1, 0, 0) and b2=(0, 1, 0).
And as the other approach, use an anchor vector when d is not 0, exactly as it is described there, no changes needed.
Summary: 2 different solutions:
Use Eugen's answer answer and for the case of zn=0, take: b1=(-yn, xn, 0) and b2=(0, 0, 1).
A different approach: If both xn and yn equal 0, take b1=(1, 0, 0) and b2=(0, 1, 0), otherwise take b1=(-yn, xn, 0) and b2=cross_product(b1, n).
In both solutions, use an anchor vector P0 as described by the aforementioned answer.

Resources