def __getitem__(self, index): acsi = self._acsi if isinstance(index, int): n_atoms = self._n_atoms if index >= n_atoms or index < -n_atoms: raise IndexError('index out of bounds') return Atom(self, index if index >= 0 else n_atoms + index, acsi) elif isinstance(index, slice): start, stop, step = index.indices(self._n_atoms) start = start or 0 index = np.arange(start, stop, step) if len(index): if start > stop: index = index[::-1] selstr = 'index {0}:{1}:{2}'.format(start, stop, step) return Selection(self, index, selstr, acsi, unique=True) elif isinstance(index, (list, np.ndarray)): unique = np.unique(index) if unique[0] < 0 or unique[-1] >= self._n_atoms: raise IndexError('index out of range') return Selection(self, unique, 'index ' + rangeString(index), acsi, unique=True) elif isinstance(index, (str, tuple)): return self.getHierView()[index] else: raise TypeError('invalid index')
def iterFragments(atoms): """Yield fragments, connected subsets in *atoms*, as :class:`Selection` instances.""" if not isinstance(atoms, Atomic): raise TypeError('atoms must be an Atomic instance') if isinstance(atoms, AtomGroup): ag = atoms atoms.iterFragments().next() fragments = atoms._fragments else: ag = atoms.getAtomGroup() bonds = atoms._iterBonds() fids = zeros((len(ag)), int) fdict = {} c = 0 for a, b in bonds: af = fids[a] bf = fids[b] if af and bf: if af != bf: frag = fdict[af] temp = fdict[bf] fids[temp] = af frag.extend(temp) fdict.pop(bf) elif af: fdict[af].append(b) fids[b] = af elif bf: fdict[bf].append(a) fids[a] = bf else: c += 1 fdict[c] = [a, b] fids[a] = fids[b] = c fragments = [] append = fragments.append fidset = set() indices = atoms._getIndices() for i, fid in zip(indices, fids[indices]): if fid in fidset: continue elif fid: fidset.add(fid) indices = fdict[fid] indices.sort() append(indices) else: # these are non-bonded atoms, e.g. ions append([i]) acsi = atoms.getACSIndex() for indices in fragments: yield Selection(ag, indices, 'index ' + rangeString(indices), acsi, unique=True)
def _iterFragments(atoms, ag, bonds): fids = zeros((len(ag)), int) fdict = {} c = 0 for a, b in bonds: af = fids[a] bf = fids[b] if af and bf: if af != bf: frag = fdict[af] temp = fdict[bf] fids[temp] = af frag.extend(temp) fdict.pop(bf) elif af: fdict[af].append(b) fids[b] = af elif bf: fdict[bf].append(a) fids[a] = bf else: c += 1 fdict[c] = [a, b] fids[a] = fids[b] = c fragments = [] append = fragments.append fidset = set() indices = atoms._getIndices() for i, fid in zip(indices, fids[indices]): if fid in fidset: continue elif fid: fidset.add(fid) indices = fdict[fid] indices.sort() append(indices) else: # these are non-bonded atoms, e.g. ions append([i]) acsi = atoms.getACSIndex() for indices in fragments: yield Selection(ag, indices, 'index ' + rangeString(indices), acsi, unique=True)
def __call__(self, radius, center): """Select atoms radius *radius* (Å) of *center*, which can be point(s) in 3-d space (:class:`numpy.ndarray` with shape ``(n_atoms, 3)``) or a set of atoms, e.g. :class:`.Selection`.""" try: center = center._getCoords() except AttributeError: try: ndim, shape = center.ndim, center.shape except AttributeError: raise TypeError('center must be an Atomic instance or a' 'coordinate array') else: if shape == (3, ): center = [center] elif not ndim == 2 and shape[1] == 3: raise ValueError('center.shape must be (n_atoms, 3) or' '(3,)') else: if center is None: raise ValueError('center does not have coordinate data') search = self._kdtree.search get_indices = self._kdtree.getIndices get_count = self._kdtree.getCount indices = set() update = indices.update radius = float(radius) for xyz in center: search(radius, xyz) if get_count(): update(get_indices()) indices = list(indices) if indices: indices.sort() if self._ag is None: return array(indices) else: if self._indices is not None: indices = self._indices[indices] return Selection(self._ag, array(indices), 'index ' + rangeString(indices), acsi=self._acsi, unique=True)
def __call__(self, radius, center): """Select atoms radius *radius* (Å) of *center*, which can be point(s) in 3-d space (:class:`numpy.ndarray` with shape ``(n_atoms, 3)``) or a set of atoms, e.g. :class:`.Selection`.""" try: center = center._getCoords() except AttributeError: try: ndim, shape = center.ndim, center.shape except AttributeError: raise TypeError('center must be an Atomic instance or a' 'coordinate array') else: if shape == (3,): center = [center] elif not ndim == 2 and shape[1] == 3: raise ValueError('center.shape must be (n_atoms, 3) or' '(3,)') else: if center is None: raise ValueError('center does not have coordinate data') search = self._kdtree.search get_indices = self._kdtree.getIndices get_count = self._kdtree.getCount indices = set() update = indices.update radius = float(radius) for xyz in center: search(radius, xyz) if get_count(): update(get_indices()) indices = list(indices) if indices: indices.sort() if self._ag is None: return array(indices) else: if self._indices is not None: indices = self._indices[indices] return Selection(self._ag, array(indices), 'index ' + rangeString(indices), acsi=self._acsi, unique=True)
def select(self, within, what): """Select atoms *within* of *what*. *within* is distance in Å and *what* can be point(s) in 3-d space (:class:`~numpy.ndarray` with shape N,3) or a set of atoms, i.e. :class:`~atomic.bases.Atomic` instances.""" if isinstance(what, np.ndarray): if what.ndim == 1 and len(what) == 3: what = [what] elif not (what.ndim == 2 and what.shape[1] == 3): raise ValueError('*what* must be a coordinate array, ' 'shape (N, 3) or (3,).') else: try: what = what._getCoords() except: raise TypeError('*what* must have a getCoords() method.') if not isinstance(what, np.ndarray): raise ValueError('what.getCoords() method must ' 'return a numpy.ndarray instance.') search = self._kdtree.search get_indices = self._kdtree.getIndices get_count = self._kdtree.getCount indices = set() update = indices.update within = float(within) for xyz in what: search(within, xyz) if get_count(): update(get_indices()) indices = list(indices) indices.sort() if indices: if self._indices is not None: indices = self._indices[indices] return Selection(self._ag, np.array(indices), 'index ' + rangeString(indices), acsi=self._acsi, unique=True)
def testContinuous(self): self.assertEqual(rangeString(list(range(10))), '0 to 9')
def getSelstr(self): """Return selection string that selects mapped atoms.""" return 'index ' + rangeString(self._indices)
def getSelstr(self): """Returns selection string that selects mapped atoms.""" return 'index ' + rangeString(self._indices)
def testRepeated(self): self.assertEqual( rangeString( list(range(10, 20)) + list(range(15, 20)) + list(range(30))), '0 to 29')
def testGapped(self): self.assertEqual( rangeString(list(range(-5, 10)) + list(range(15, 20)) + list(range(25, 30)), pos=False), '-5 to 9 15 to 19 25 to 29')
def testNegative(self): self.assertEqual(rangeString(list(range(-5, 10)), pos=False), '-5 to 9')
def testRepeated(self): self.assertEqual(rangeString(list(range(10, 20)) + list(range(15, 20)) + list(range(30))), '0 to 29')
def testGapped(self): self.assertEqual(rangeString(list(range(-5, 10)) + list(range(15, 20)) + list(range(25, 30)), pos=False), '-5 to 9 15 to 19 25 to 29')