Source code for sknano.core.atoms.mixins.kdtree_atoms

# -*- coding: utf-8 -*-
"""
===============================================================================
Mixin classes for KDTree analysis (:mod:`sknano.core.atoms.kdtree_atoms`)
===============================================================================

.. currentmodule:: sknano.core.atoms.kdtree_atoms

"""
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals
__docformat__ = 'restructuredtext en'

from abc import ABCMeta, abstractmethod

# import warnings
# warnings.filterwarnings('ignore', "Mean of empty slice.")
# warnings.filterwarnings('ignore',
#                         'invalid value encountered in double_scalars')

import numpy as np

from sknano.core import dedupe, flatten

__all__ = ['KDTreeAtomsMixin']


[docs]class KDTreeAtomsMixin(metaclass=ABCMeta): """Mixin Atoms class for KDTree analysis.""" @property @abstractmethod def atom_tree(self): """:class:`~scipy:scipy.spatial.KDTree` of atom coordinates.""" raise NotImplementedError
[docs] def query_atom_tree(self, k=16, eps=0, p=2, rc=np.inf): """Query atom tree for nearest neighbors distances and indices. Parameters ---------- k : integer The number of nearest neighbors to return. eps : nonnegative float Return approximate nearest neighbors; the kth returned value is guaranteed to be no further than (1+eps) times the distance to the real kth nearest neighbor. p : float, 1<=p<=infinity Which Minkowski p-norm to use. 1 is the sum-of-absolute-values "Manhattan" distance 2 is the usual Euclidean distance infinity is the maximum-coordinate-difference distance rc : nonnegative float Radius cutoff. Return only neighbors within this distance. This is used to prune tree searches, so if you are doing a series of nearest-neighbor queries, it may help to supply the distance to the nearest neighbor of the most recent point. Returns ------- d : array of floats The distances to the nearest neighbors, sorted by distance. i : array of integers The locations of the neighbors in self.atom_tree.data. `i` is the same shape as `d`. """ atom_tree = self.atom_tree if atom_tree is not None: d, i = atom_tree.query(np.asarray(self.coords), k=k+1, eps=eps, p=p, distance_upper_bound=rc) return d[:, 1:], i[:, 1:]
[docs] def query_ball_point(self, pts, r, p=2.0, eps=0): """Find all `Atoms` within distance `r` of point(s) `pts`. Parameters ---------- pts : :class:`~sknano.core.math.Point` The :class:`~sknano.core.math.Point` or :class:`~sknano.core.math.Points` to search for neighbors of. r : positive :class:`~python:float` The radius of :class:`~sknano.core.atoms.KDTAtoms` to return p : float, 1<=p<=infinity Which Minkowski p-norm to use. 1 is the sum-of-absolute-values "Manhattan" distance 2 is the usual Euclidean distance infinity is the maximum-coordinate-difference distance eps : nonnegative :class:`~python:float`, optional Approximate search. Returns ------- :class:`~sknano.core.atoms.Atoms` """ atom_tree = self.atom_tree if atom_tree is not None: NNi = \ list(dedupe(flatten( atom_tree.query_ball_point(pts, r, p=p, eps=eps)))) return self.__class__(atoms=np.asarray(self)[NNi].tolist(), **self.kwargs)
[docs] def query_ball_tree(self, other, r, p=2.0, eps=0): """Find all pairs of `Atoms` whose distance is at more `r`. Parameters ---------- other : :class:`~scipy:scipy.spatial.KDTree` The tree containing points to search against r : positive :class:`~python:float` The radius of :class:`~sknano.core.atoms.KDTAtoms` to return p : float, 1<=p<=infinity Which Minkowski p-norm to use. 1 is the sum-of-absolute-values "Manhattan" distance 2 is the usual Euclidean distance infinity is the maximum-coordinate-difference distance eps : nonnegative :class:`~python:float`, optional Approximate search. Returns ------- :class:`~sknano.core.atoms.Atoms` """ atom_tree = self.atom_tree if atom_tree is not None: # NNi = \ # atom_tree.query_ball_tree(other.atom_tree, r, p=p, eps=eps) NNi = \ other.atom_tree.query_ball_tree(atom_tree, r, p=p, eps=eps) NNi = list(dedupe(flatten(NNi))) return self.__class__(atoms=np.asarray(self)[NNi].tolist(), **self.kwargs)
[docs] def query_pairs(self, r, p=2.0, eps=0): """Find all pairs of points within a distance `r`. Parameters ---------- r : positive float p : float, optional eps : float, optional Returns ------- results : set """ atom_tree = self.atom_tree if atom_tree is not None: return atom_tree.query_pairs(r, p=p, eps=eps)
[docs] def count_neighbors(self, other, r, p=2.0): """Count how many nearby neighbor pairs can be formed. Count the number of pairs (x1, x2) that can be formed, with `x1` drawn from `self` and `x2` drawn from `other`, and where ``distance(x1, x2, p) <= r``. Parameters ---------- other : `KDTree` r : float or one-dimensional array of floats p : float, 1<=p<=infinity, optional Returns ------- result : int or 1-D array of ints """ atom_tree = self.atom_tree if atom_tree is not None: return atom_tree.count_neighbors(other, r, p=p)