Python - Get the coordinates of densest point - python

I'm using numpy and scipy to generate a density plot from 3D coordinate information. I can generate a density plot of the data successfully by generating a KDE with the following code
xyz = np.vstack([x,y,z])
kde = stats.gaussian_kde(xyz)
density = kde(xyz)
But how can I use this information to find the coordinates that associate with the 3D point of greatest density?
I've tried
max(density)
which returns a value that I can then find the index of with
density.argmax(axis=0)
but then I hit a blank as I can't seem to use that index to grab the associated coordinates from xyz and I'm unsure if this is the right approach.

From here, I can use
xyz.T[np.argmax(density)]
to return the 3D coordinates of the densest point in my data

Related

In which field does 3d graph plotting used?

We know that we can plot 3d graphs in MatPlotLib but in which field does it used and for what purpose
3D graphs are used when you need to establish the relationship between 3 variables(x,y and z).
This application can be used in the following fields:
1)geographical area: In this field X,Y is used as latitude,longitude and Z can be used as Altitude to replicate the geographical area like hills,buildings etc..
2)Geometry: To visualize the 3d objects like plane,sphere,cube etc in three dimensional space we use 3d plotting.
3)Statistics: To compare two variables on third variable we use 3d plots like 3d barchart, Scatter plot etc..
There are many other fields where 3d plotting is used instead of 2d plot, as it provides more information visually.
When you are working with 3 variables and want to plot a graph in between them and identify the relationship between them then you should use 3d graphs.
There can be many use cases of 3d plots:
To describe the position of a point in a plane if the position varies with time, we now need 3 measurements- x-axis distance, y-axis distance, and time elapsed.
To describe the position of a point in 3D space, we need 3 measurements: x distance, y distance and z distance.
To describe the position of a point in 3D space, if the position varies with time, we need 4 measurements: x distance, y distance, z distance and time.
Each of those measurements represents a dimension, and each dimension requires it’s own axis.
Follow this docs for more information

Finding intersection points between .stl (CAD drawing) file and 3D plot (matplotlib)?

I am trying to find intersection points between 3d object .stl file (that I imported to python using numpy-stl) and 3d plot(that I generated using matplotlib). The 3d object is a cad drawing and 3d plot is a bunch of curves in 3d. I can plot them on the same figure but I have no idea how I can find intersection points between the trajectory and the drawing. My idea was to convert the curve into .stl using save() function from the numpy-stl module after plotting it and show them together on a cad application like freeCAD together and find intersection using the application's functionality. But it does not work as simple because the plots are point based and .stl is triangle based. If anyone has any advice on how to approach this problem, please let me know!!
Here is the code to plot both .stl object and the 3d plot. This is what I have so far.
#allInitialE is 1D list, allX, allY, allZ are all 2D lists
from stl import mesh
from numpy import *
from mpl_toolkits import mplot3d
from matplotlib import pyplot as plt
fig = plt.figure()
ax = plt.axes(projection = '3d')
your_mesh = mesh.Mesh.from_file('fileName.stl')
your_mesh.translate([0,7,0])
ax.add_collection3d(mplot3d.art3d.Poly3DCollection(your_mesh.vectors))
ax.view_init(azim = -90, elev = 0)
maxE = max(allInitialE)
ax.set_xlabel('x axis (m)') # y and z are flipped to make it easier for me to visualize
ax.set_ylabel('z axix (m)')
ax.set_zlabel('y axix (m)')
plt.title('Particle Trajectory')
for k in range(numParticles): #iterate through each of the particles' xyz data
e = allInitialE[k]
if e < maxE/3:
ax.plot3D(allX[k], allZ[k], allY[k], 'g-')
elif e < maxE/2:
ax.plot3D(allX[k], allZ[k], allY[k], 'b-')
else:
ax.plot3D(allX[k], allZ[k], allY[k], 'r-')
plt.show()
1 idea: Is there any way to convert .stl object to a set of plane functions? If so, I could make the plots into lines and find intersection between the plane and the line?
2nd idea: Or, since .stl are vector based, I can use vector calculation? i.e. see if a vector on a curve (line segment) has a common point as a triangle on a .stl object (triangle is defined by three vectors).
Please give me any idea you may have! Thank you so much.
Another way might be to use VTK. You can convert your numpy-stl object (obj) to a vtkPolyData
import vedo
import vtk
import itertools
obj = your_mesh
verts = list(itertools.chain(*(obj.vectors)))
faces = [[i*3, i*3+1, i*3+2] for i in range(len(verts)//3)]
vpoly = vedo.Mesh([verts, faces]).clean().polydata()
Then you could use vtkCutter https://discourse.vtk.org/t/get-intersection-of-polydata-line-and-a-plane/3894/3 or vtkIntersectionPolyDataFilter VTK check polydata point objects for intersection
Concerning your 1st idea, yes, you can convert your STL file into a set of triangles, just check out:
your_mesh.vectors
which is an array of triangle 3D vertices. From those you can construct a plane, and then calculate intersection between segment and plane.
Concerning the 2nd idea, you could do that only if your trajectory crosses exactly to a vertex, otherwise it would not detect the intersection. (Or you would need to give it a margin).
I found a way using pyoctree, which has a function to find intersection between line segments and mesh. Here is the link: https://pypi.org/project/pyoctree/
I was able to use rayIntersection() to do what I wanted to do, really quick. This Intersection between line and triangle in 3D also helped, but the calculation was very slow when it dealt with 60K+ points in a curve.

Getting a good interpolation/fit for 1d curve in 3d space -- Python

I have a set of 3d coordinates (x,y,z) to which I would like to fit a space curve. Does anyone know of existing routines for this in Python?
From what I have found (https://docs.scipy.org/doc/scipy/reference/interpolate.html), there are existing modules for fitting a curve to a set of 2d coordinates, and others for fitting a surface to a set of 3d coordinates. I want the middle path - fitting a curve to a set of 3d coordinates.
EDIT --
I found an explicit answer to this on another post here, using interpolate.splprep() and interpolate.splenv(). Here are my data points:
import numpy as np
data = np.array([[21.735556483642707, 7.9999120559310359, -0.7043281314370935],
[21.009401429607784, 8.0101161320825103, -0.16388503829177037],
[20.199370045383134, 8.0361339131845497, 0.25664085801558179],
[19.318149385194054, 8.0540100864979447, 0.50434139043379278],
[18.405497793567243, 8.0621753888918484, 0.57169888018720161],
[17.952649703401562, 8.8413995204241491, 0.39316793526155014],
[17.539007529982641, 9.6245700151356104, 0.14326173861202204],
[17.100154581079089, 10.416295524018977, 0.011339000091976647],
[16.645143439968102, 11.208477191735446, 0.070252116425261066],
[16.198247656768263, 11.967005154933993, 0.31087815045809558],
[16.661378578010989, 12.717314230004659, 0.54140549139204996],
[17.126106263351478, 13.503461982612732, 0.57743407626794219],
[17.564249250974573, 14.28890107482801, 0.42307198199366186],
[17.968265052275274, 15.031985807202176, 0.10156997950061938]])
Here is my code:
from scipy import interpolate
from mpl_toolkits.mplot3d import Axes3D
data = data.transpose()
#now we get all the knots and info about the interpolated spline
tck, u= interpolate.splprep(data, k=5)
#here we generate the new interpolated dataset,
#increase the resolution by increasing the spacing, 500 in this example
new = interpolate.splev(np.linspace(0,1,500), tck, der=0)
#now lets plot it!
fig = plt.figure()
ax = Axes3D(fig)
ax.plot(data[0], data[1], data[2], label='originalpoints', lw =2, c='Dodgerblue')
ax.plot(new[0], new[1], new[2], label='fit', lw =2, c='red')
ax.legend()
plt.savefig('junk.png')
plt.show()
This is the image:
You can see that the fit is not good, while I am already using the maximum allowed fitting order value (k=5). Is this because the curve is not fully convex? Does anyone know how I can improve the fit?
Depends on what the points represent, but if it's just position data, you could use a kalman filter such as this one written in python. You could just query the kalman filter at any time to get the "expected point" at that time, so it would work just like a function of time.
If you do plan to use a kalman filter, just set the initial estimate to your first coordinate, and set your covariance to be a diagonal matrix of huge numbers, this will indicate that you are very uncertain about the position of your next point, which will quickly lock the filter onto your coordinates.
You'd want to stay away from spline fitting methods, because splines will always go through your data.
You can fit a curve to any dimensional data. The curve fitting / optimization algorithms (say, in scipy.optimize) all treat the observations you want to model as a plain 1-d array, and do not care what the independent variables are. If you flatten your 3d data, each value will correspond to an (x, y, z) tuple. You can just pass that information along as "extra" data to you fitting routine to help you calculate the model curve that will be fitted to your data.

Streamlines on a triangulation with matplotlib

I made a triangulation object in matplotlib (out of the P matrix, which contains points coordinates, and the T matrix, which contains the triangles nodes, that describe a rectangle minus a hole) and computed some scalar field called phi at the nodes of this triangulation (using a finite element method applied to a Poisson equation). Using this triangulation I compute the gradient, which is what I am interested in. I made a quiver plot of this vector field, everything is nice, the vectors don't intersect with the hole.
However, when I want to plot streamlines via the streamplot function, they intersect the hole, like in the following figure:
The thing is, in order to trace streamlines, I have to create a structured grid for the streamplot function. But since my vector field is not defined at the nodes of the regular grid, I need to interpolate the values at these nodes. For that I used griddata. The problem is, in doing so, the hole is covered by the regular grid so the vector field becomes defined inside the hole, hence the result. Here is the relevant piece of code that produced the picture:
def plot_streamlines(P, T, phi):
triangulation = tr.Triangulation(P[:,0], P[:,1], T)
interpolator = tr.CubicTriInterpolator(triangulation, phi)
(u_x,u_y) = interpolator.gradient(triangulation.x, triangulation.y)
grid_x, grid_y = np.mgrid[x_min:x_max:100j, y_min:y_max:100j]
grid_u_x = ip.griddata(P, u_x, (grid_x,grid_y), method='cubic')
grid_u_y = ip.griddata(P, u_y, (grid_x,grid_y), method='cubic')
pl.streamplot(grid_x[:,0], grid_y[0,:], -grid_u_x.T, -grid_u_y.T)
I am aware of masked arrays but didn't manage to use the mask to get the result I wanted. I wanted to create a kind of masked regulard grid and then interpolate the vector field on it, but I didn't manage to do it. Does somebody has experience with this kind of problem? Any suggestion will be appreciated.
Thanks!
In your code sample interpolator.gradientis already an interpolator i.e. you do not need to use it in combination with griddata. Try:
grid_u_x, grid_u_y = interpolator.gradient(grid_x, grid_y)
As this interpolator is aware of your triangulation mesh, it should result is a velocity vector filled of nan outside your mesh. Streamplot should hopefully be able to handle this gracefully as in this example:
http://matplotlib.org/examples/images_contours_and_fields/streamplot_demo_masking.html

Interpolation over an irregular grid

So, I have three numpy arrays which store latitude, longitude, and some property value on a grid -- that is, I have LAT(y,x), LON(y,x), and, say temperature T(y,x), for some limits of x and y. The grid isn't necessarily regular -- in fact, it's tripolar.
I then want to interpolate these property (temperature) values onto a bunch of different lat/lon points (stored as lat1(t), lon1(t), for about 10,000 t...) which do not fall on the actual grid points. I've tried matplotlib.mlab.griddata, but that takes far too long (it's not really designed for what I'm doing, after all). I've also tried scipy.interpolate.interp2d, but I get a MemoryError (my grids are about 400x400).
Is there any sort of slick, preferably fast way of doing this? I can't help but think the answer is something obvious... Thanks!!
Try the combination of inverse-distance weighting and
scipy.spatial.KDTree
described in SO
inverse-distance-weighted-idw-interpolation-with-python.
Kd-trees
work nicely in 2d 3d ..., inverse-distance weighting is smooth and local,
and the k= number of nearest neighbours can be varied to tradeoff speed / accuracy.
There is a nice inverse distance example by Roger Veciana i Rovira along with some code using GDAL to write to geotiff if you're into that.
This is of coarse to a regular grid, but assuming you project the data first to a pixel grid with pyproj or something, all the while being careful what projection is used for your data.
A copy of his algorithm and example script:
from math import pow
from math import sqrt
import numpy as np
import matplotlib.pyplot as plt
def pointValue(x,y,power,smoothing,xv,yv,values):
nominator=0
denominator=0
for i in range(0,len(values)):
dist = sqrt((x-xv[i])*(x-xv[i])+(y-yv[i])*(y-yv[i])+smoothing*smoothing);
#If the point is really close to one of the data points, return the data point value to avoid singularities
if(dist<0.0000000001):
return values[i]
nominator=nominator+(values[i]/pow(dist,power))
denominator=denominator+(1/pow(dist,power))
#Return NODATA if the denominator is zero
if denominator > 0:
value = nominator/denominator
else:
value = -9999
return value
def invDist(xv,yv,values,xsize=100,ysize=100,power=2,smoothing=0):
valuesGrid = np.zeros((ysize,xsize))
for x in range(0,xsize):
for y in range(0,ysize):
valuesGrid[y][x] = pointValue(x,y,power,smoothing,xv,yv,values)
return valuesGrid
if __name__ == "__main__":
power=1
smoothing=20
#Creating some data, with each coodinate and the values stored in separated lists
xv = [10,60,40,70,10,50,20,70,30,60]
yv = [10,20,30,30,40,50,60,70,80,90]
values = [1,2,2,3,4,6,7,7,8,10]
#Creating the output grid (100x100, in the example)
ti = np.linspace(0, 100, 100)
XI, YI = np.meshgrid(ti, ti)
#Creating the interpolation function and populating the output matrix value
ZI = invDist(xv,yv,values,100,100,power,smoothing)
# Plotting the result
n = plt.normalize(0.0, 100.0)
plt.subplot(1, 1, 1)
plt.pcolor(XI, YI, ZI)
plt.scatter(xv, yv, 100, values)
plt.title('Inv dist interpolation - power: ' + str(power) + ' smoothing: ' + str(smoothing))
plt.xlim(0, 100)
plt.ylim(0, 100)
plt.colorbar()
plt.show()
There's a bunch of options here, which one is best will depend on your data...
However I don't know of an out-of-the-box solution for you
You say your input data is from tripolar data. There are three main cases for how this data could be structured.
Sampled from a 3d grid in tripolar space, projected back to 2d LAT, LON data.
Sampled from a 2d grid in tripolar space, projected into 2d LAT LON data.
Unstructured data in tripolar space projected into 2d LAT LON data
The easiest of these is 2. Instead of interpolating in LAT LON space, "just" transform your point back into the source space and interpolate there.
Another option that works for 1 and 2 is to search for the cells that maps from tripolar space to cover your sample point. (You can use a BSP or grid type structure to speed up this search) Pick one of the cells, and interpolate inside it.
Finally there's a heap of unstructured interpolation options .. but they tend to be slow.
A personal favourite of mine is to use a linear interpolation of the nearest N points, finding those N points can again be done with gridding or a BSP. Another good option is to Delauney triangulate the unstructured points and interpolate on the resulting triangular mesh.
Personally if my mesh was case 1, I'd use an unstructured strategy as I'd be worried about having to handle searching through cells with overlapping projections. Choosing the "right" cell would be difficult.
I suggest you taking a look at GRASS (an open source GIS package) interpolation features (http://grass.ibiblio.org/gdp/html_grass62/v.surf.bspline.html). It's not in python but you can reimplement it or interface with C code.
Am I right in thinking your data grids look something like this (red is the old data, blue is the new interpolated data)?
alt text http://www.geekops.co.uk/photos/0000-00-02%20%28Forum%20images%29/DataSeparation.png
This might be a slightly brute-force-ish approach, but what about rendering your existing data as a bitmap (opengl will do simple interpolation of colours for you with the right options configured and you could render the data as triangles which should be fairly fast). You could then sample pixels at the locations of the new points.
Alternatively, you could sort your first set of points spatially and then find the closest old points surrounding your new point and interpolate based on the distances to those points.
There is a FORTRAN library called BIVAR, which is very suitable for this problem. With a few modifications you can make it usable in python using f2py.
From the description:
BIVAR is a FORTRAN90 library which interpolates scattered bivariate data, by Hiroshi Akima.
BIVAR accepts a set of (X,Y) data points scattered in 2D, with associated Z data values, and is able to construct a smooth interpolation function Z(X,Y), which agrees with the given data, and can be evaluated at other points in the plane.

Categories

Resources