Source code for ddd_pylib.points_manip._merge_close_points_operator
from ddd_pylib._base import PointsOperator
from scipy.spatial import KDTree
import pandas as pd
[docs]
class MergeClosePointsOperator(PointsOperator):
def __init__(self):
super().__init__()
self._distanceThreshold = self.defaultDistanceThreshold()
[docs]
@staticmethod
def defaultDistanceThreshold():
return 1.0
[docs]
def getDistanceThreshold(self):
"""
Return the distance threshold value
"""
return self._distanceThreshold
[docs]
def setDistanceThreshold(self, threshold):
"""
Set the distance threshold value
Args:
threshold: The distance threshold value
"""
self._distanceThreshold = threshold
[docs]
def getPrefix(self):
return "Merged-"
def _mergeByDistance(self, df: pd.DataFrame, threshold: float) -> pd.DataFrame:
spatial_axes = [ax for ax in self.getValidAxes() if ax != 'T']
used_points = set()
merged_points = []
if df.empty:
return df
tree = KDTree(df[spatial_axes].values)
for i, point in df[spatial_axes].iterrows():
if i in used_points:
continue
indices = tree.query_ball_point(point.values, threshold)
merged_point = df.iloc[indices].mean()
merged_points.append(merged_point)
used_points.update(indices)
return pd.DataFrame(merged_points, columns=df.columns)
def _applyToFrame(self, frameData, t, nT):
df = frameData[0]
t = self.getDistanceThreshold()
return self._mergeByDistance(df, t)
if __name__ == "__main__":
import pandas as pd
import numpy as np
import napari
points = np.random.rand(1500, 3) * 100
df = pd.DataFrame(points, columns=['X', 'Y', 'Z'])
op = MergeClosePointsOperator()
op.setMainDataFrame(df)
op.setDistanceThreshold(5.0)
op.run()
res = op.getResult()
viewer = napari.Viewer()
viewer.add_points(
df[['Z', 'Y', 'X']].values,
size=1,
face_color='red',
name='Original Points'
)
viewer.add_points(
res[['Z', 'Y', 'X']].values,
size=1,
face_color='transparent',
border_color='green',
name='Merged Points'
)
napari.run()