Visualizing 3D hulls around clusters in Python

113 Views Asked by At

Problem I have a dataset consiting of 3D coordinates (x,y,z) and I want to visualize the hull of each cluster separately, conserving complex spatial structures of the data, such as in the following examples: A) Example image B) Example image

What I have tried:

  • matplotlib's convex hull: This does not seem to be able to conserve the spatial structure such as "holes" or rings, but instead builds a convex hull around all given data points
  • mayavi's mlab: This seems to work well for continuous functions, such as np.sin(x)*np.cos(x)*np.sin(z) for example, but not for datasets of discrete points as in my case.
1

There are 1 best solutions below

0
On BEST ANSWER

An example, based on the answers to How to plot a 3D density map in python with matplotlib and 3D Contour plot from data using Mayavi / Python, is to use a Gaussian KDE and generate a 3D contour plot of the output using mayavi:

from scipy.stats import gaussian_kde
from mayavi.mlab import contour3d

import numpy as np

# generate some random points
npoints = 10_000

x = np.random.rand(npoints)
y = np.sin(2 * np.pi * x * 0.75 + 0.1) + 0.4 * np.random.randn(len(x))
z = np.cos(2 * np.pi * x * 0.3 + 0.6) + np.sin(2 * np.pi * y) + 0.4 * np.random.randn(len(x))

# construct a Gaussian KDE
xyz = np.vstack([x, y, z])
kde = gaussian_kde(xyz)

# evaluate the KDE on a grid
xmin, ymin, zmin = x.min(), y.min(), z.min()
xmax, ymax, zmax = x.max(), y.max(), z.max()
xi, yi, zi = np.mgrid[xmin:xmax:30j, ymin:ymax:30j, zmin:zmax:30j]
coords = np.vstack([item.ravel() for item in [xi, yi, zi]])
density = kde(coords).reshape(xi.shape)

# create the contour plot (for some reason contours must be at least
# 3 to show anything!)
contour3d(xi, yi, zi, density, contours=3, transparent=True)

This produces:

enter image description here

I'm sure a lot could be done within mayavi to prettify this.