class CoordinateNeighborSearch(object): """ This class can be used for two related purposes: 1. To find all indices of a coordinate list within radius of a given query position. 2. To find all indices of a coordinate list that are within a fixed radius of each other. CoordinateNeighborSearch makes use of the KDTree C++ module, so it's fast. """ def __init__(self, coordinates, bucket_size=10): # , copy=True): """ :Arguments: *coordinates* list of N coordinates (Nx3 numpy array) *bucket_size* bucket size of KD tree. You can play around with this to optimize speed if you feel like it. """ # to Nx3 array of type float (required for the C++ code) ## (also force a copy by default and make sure that the array order is compatible ## with the C++ code) ##self.coords=numpy.array(coordinates,dtype=numpy.float32,copy=copy,order='C') self.coords = numpy.asarray(coordinates, dtype=numpy.float32, order='C') assert (self.coords.dtype == numpy.float32) assert (bucket_size > 1) assert (self.coords.shape[1] == 3) self.kdt = KDTree(3, bucket_size) self.kdt.set_coords(self.coords) def search(self, center, radius, distances=False): """Neighbor search. Return all indices in the coordinates list that have at least one atom within *radius* of *center*. :Arguments: * center numpy array * radius float * distances bool ``True``: return (indices,distances); ``False``: return indices only """ self.kdt.search(center, radius) if distances: return self.kdt.get_indices(), self.kdt.get_radii() else: return self.kdt.get_indices() def search_list(self, centers, radius): """Search neighbours near all centers. Returns all indices that are within *radius* of any center listed in *centers*, i.e. "find all A within R of B" where A are the coordinates used for setting up the CoordinateNeighborSearch and B are the centers. :Arguments: *centers* Mx3 numpy array of M centers *radius* float """ self.kdt.list_search(centers, radius) return self.kdt.list_get_indices() def search_all(self, radius, distances=False): """All neighbor search. Return all index pairs corresponding to coordinates within the *radius*. :Arguments: *radius* float *distances* bool ``True``: return (indices,distances); ``False``: return indices only [``False``] """ self.kdt.all_search(radius) if distances: return self.kdt.all_get_indices(), self.kdt.all_get_radii() else: return self.kdt.all_get_indices() def _distances(self): """Return all distances after search().""" return self.kdt.get_radii() def _distances_all(self): """Return all distances after search_all().""" return self.kdt.all_get_radii()