I have a set of data points (as scattered data points in black) and I want to draw their outermost contour. I have tried to calculate the convex hull of my points (code below) but I lose too much resolution and the shape loses its nuances.
# load usual stuff
from __future__ import print_function
import sys, os
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib import colors
from scipy.spatial import ConvexHull
# read input file
cbm_contour = sys.argv[1]
def parse_pdb_coords(file):
f = open(file, "r")
coords = X = np.empty(shape=[0, 3])
while True:
line = f.readline()
if not line: break
if line.split()[0] == "ATOM" or line.split()[0] == "HETATM":
Xcoord = float(line[30:38])
Ycoord = float(line[38:46])
Zcoord = float(line[46:54])
coords = np.append(coords, [[Xcoord, Ycoord, Zcoord]], axis=0)
return coords
##########################################################################
plt.figure(figsize=(11, 10))
# parse input file
cbm_coords = parse_pdb_coords(cbm_contour)
# consider only x- and y-axis coordinates
flattened_points = cbm_coords[:, :2]
x = cbm_coords[:,0]
y = cbm_coords[:,1]
# Find the convex hull of the flattened points
hull = ConvexHull(flattened_points)
for simplex in hull.simplices:
plt.plot(flattened_points[simplex, 0], flattened_points[simplex, 1], color='red', lw=2)
plt.scatter(cbm_coords[:,0], cbm_coords[:,1], s=1, c='black')
plt.xlabel('X-axis coordinate ($\mathrm{\AA} $)', size=16)
plt.ylabel('Y-axis distance ($\mathrm{\AA} $)', size=16)
plt.yticks(np.arange(-20, 24, 4),size=16)
plt.xticks(np.arange(-20, 24, 4),size=16)
plt.savefig("example.png", dpi=300, transparent=False)
plt.show()
Note that this can't be transformed to a 'minimal working example' due to the complexity of the data points, but my dataset can be downloaded here. The idea is to have a generalized solution for other datasets too.
Does anyone have a suggestion?

You could use an Alpha Shape instead of your Convex Hull, for instance using the
alphashapelibrary.You will have to test different values for
alphato find one that suits your needs. Herealpha=1did a good job.Output:
Assuming such input as
arr(X, Y, Z):NOTE
If you get the following error:
Then your version of
shapelyis too recent fordescartes. You can fix the issue by following instructions here.