def make_topology(extras=None, size=None): """Reference topology system Parameters ---------- extras : list of strings attributes to add to the Universe size : tuple of natoms, nres, nseg by default: (125 atoms, 25 residue, 5 segments) Returns ------- MDAnalysis.core.topology.Topology object """ from MDAnalysis.core.topology import Topology if extras is None: extras = [] if size is None: size = _N_ATOMS, _N_RESIDUES, _N_SEGMENTS attrs = [_MENU[extra](size) for extra in extras] return Topology(size[0], size[1], size[2], attrs=attrs, atom_resindex=np.repeat(np.arange(size[1]), size[0] // size[1]), residue_segindex=np.repeat(np.arange(size[2]), size[1] // size[2]))
def top(self): Ridx = np.array([0, 0, 2, 2, 1, 1, 3, 3, 1, 2]) Sidx = np.array([0, 1, 1, 0]) return Topology(10, 4, 2, attrs=[self.attrclass(self.values.copy())], atom_resindex=Ridx, residue_segindex=Sidx)
def parse(self, **kwargs): pbmol = next(pybel.readfile('cif', self.filename)) unpack_symmetry(pbmol) natoms = len(pbmol.atoms) names = np.zeros(natoms, dtype=object) charges = np.zeros(natoms, dtype=np.float32) masses = np.zeros(natoms, dtype=np.float64) for i, atom in enumerate(pbmol.atoms): names[i] = atom.type masses[i] = atom.exactmass charges[i] = atom.partialcharge attrs = [ Atomnames(names), Charges(charges), Masses(masses), Resids(np.array([1])), Resnums(np.array([1])), Segids(np.array(['SYSTEM'], dtype=object)), ] return Topology(natoms, 1, 1, attrs=attrs)
def setUp(self): self.top = Topology(10, 4, 2, attrs=[self.attrclass(self.values.copy())], atom_resindex=self.Ridx, residue_segindex=self.Sidx) self.attr = getattr(self.top, self.attrclass.attrname)
def setUp(self): names = self.names = ta.Atomnames( np.array(['A', 'B', 'C'], dtype=object)) types = self.types = ta.Atomtypes(np.array(['X', 'Y', 'Z'], dtype=object), guessed=True) resids = self.resids = ta.Resids(np.array([1])) resnames = self.resnames = ta.Resnames(np.array(['ABC'], dtype=object), guessed=True) self.top = Topology(n_atoms=3, n_res=1, attrs=[names, types, resids, resnames])
def parse(self): """ Access ESPResSo data and return the topology object Returns ------- top : :class:`MDAnalysis.core.topology.Topology` a topology object """ espresso = self.kwargs['espresso'] names = [] atomtypes = [] masses = [] charges = [] for p in espresso.part: names.append("A" + repr(p.type)) atomtypes.append("T" + repr(p.type)) masses.append(p.mass) charges.append(p.q) natoms = len(espresso.part) attrs = [ Atomnames(np.array(names, dtype=object)), Atomids(np.arange(natoms) + 1), Atomtypes(np.array(atomtypes, dtype=object)), Masses(masses), Resids(np.array([1])), Resnums(np.array([1])), Segids(np.array(['System'], dtype=object)), AltLocs(np.array([' '] * natoms, dtype=object)), Resnames(np.array(['R'], dtype=object)), Occupancies(np.zeros(natoms)), Tempfactors(np.zeros(natoms)), ICodes(np.array([' '], dtype=object)), Charges(np.array(charges)), ] top = Topology(natoms, 1, 1, attrs=attrs) return top
def from_atomgroup(cls, *args): """Create a new new :class:`Structure` from one or more ``AtomGroup`` instances. Parameters ---------- *args : ``AtomGroup`` One or more AtomGroups. Returns ------- structure : :class:`Structure` Raises ------ ValueError Too few arguments or an AtomGroup is empty and TypeError Arguments are not :class:`AtomGroup` instances. Notes ----- This is take straight from ``MDAnalysis.universe``. Refer to that module for more information. """ from MDAnalysis.coordinates.memory import MemoryReader from MDAnalysis.topology.base import squash_by from MDAnalysis.core import groups from MDAnalysis.core.topology import Topology from MDAnalysis.core.topologyattrs import AtomAttr, ResidueAttr, SegmentAttr if len(args) == 0: raise ValueError("Need at least one AtomGroup for merging") for a in args: if not isinstance(a, groups.AtomGroup): raise TypeError(repr(a) + " is not an AtomGroup") for a in args: if len(a) == 0: raise ValueError("cannot merge empty AtomGroup") # Create a new topology using the intersection of topology attributes blank_topology_attrs = set(dir(Topology(attrs=[]))) common_attrs = set.intersection( *[set(dir(ag.universe._topology)) for ag in args]) tops = set(["bonds", "angles", "dihedrals", "impropers"]) attrs = [] # Create set of attributes which are array-valued and can be simply # concatenated together common_array_attrs = common_attrs - blank_topology_attrs - tops # Build up array-valued topology attributes including only attributes # that all arguments' universes have for attrname in common_array_attrs: for ag in args: attr = getattr(ag, attrname) attr_class = type(getattr(ag.universe._topology, attrname)) if issubclass(attr_class, AtomAttr): pass elif issubclass(attr_class, ResidueAttr): attr = getattr(ag.residues, attrname) elif issubclass(attr_class, SegmentAttr): attr = getattr(ag.segments, attrname) else: raise NotImplementedError("Don't know how to handle" " TopologyAttr not subclassed" " from AtomAttr, ResidueAttr," " or SegmentAttr.") if type(attr) != np.ndarray: raise TypeError("Encountered unexpected topology " "attribute of type {}".format(type(attr))) try: attr_array.extend(attr) except NameError: attr_array = list(attr) attrs.append(attr_class(np.array(attr_array, dtype=attr.dtype))) del attr_array # Build up topology groups including only those that all arguments' # universes have for t in tops & common_attrs: offset = 0 bondidx = [] types = [] for ag in args: # create a mapping scheme for this atomgroup mapping = {a.index: i for i, a in enumerate(ag, start=offset)} offset += len(ag) tg = getattr(ag, t) bonds_class = type(getattr(ag.universe._topology, t)) # Create a topology group of only bonds that are within this ag # ie we don't want bonds that extend out of the atomgroup tg = tg.atomgroup_intersection(ag, strict=True) # Map them so they refer to our new indices new_idx = [ tuple([mapping[x] for x in entry]) for entry in tg.indices ] bondidx.extend(new_idx) if hasattr(tg, "_bondtypes"): types.extend(tg._bondtypes) else: types.extend([None] * len(tg)) if any(t is None for t in types): attrs.append(bonds_class(bondidx)) else: types = np.array(types, dtype="|S8") attrs.append(bonds_class(bondidx, types)) # Renumber residue and segment indices n_atoms = sum([len(ag) for ag in args]) residx = [] segidx = [] res_offset = 0 seg_offset = 0 for ag in args: # create a mapping scheme for this atomgroup's parents res_mapping = { r.resindex: i for i, r in enumerate(ag.residues, start=res_offset) } seg_mapping = { r.segindex: i for i, r in enumerate(ag.segments, start=seg_offset) } res_offset += len(ag.residues) seg_offset += len(ag.segments) # Map them so they refer to our new indices residx.extend([res_mapping[x] for x in ag.resindices]) segidx.extend([seg_mapping[x] for x in ag.segindices]) residx = np.array(residx, dtype=np.int32) segidx = np.array(segidx, dtype=np.int32) _, _, [segidx] = squash_by(residx, segidx) n_residues = len(set(residx)) n_segments = len(set(segidx)) top = Topology( n_atoms, n_residues, n_segments, attrs=attrs, atom_resindex=residx, residue_segindex=segidx, ) # Create and populate a universe coords = np.vstack([a.positions for a in args]) u = cls(top, coords[None, :, :], format=MemoryReader) return u
def test_segindex_VE(self): # wrong sized residue to segment array AR = np.arange(5) RS = np.arange(10) with pytest.raises(ValueError): Topology(n_atoms=5, n_res=5, atom_resindex=AR, residue_segindex=RS)
def test_resindex_VE(self): # wrong sized atom to residue array AR = np.arange(10) with pytest.raises(ValueError): Topology(n_atoms=5, atom_resindex=AR)
def test_make_topology_no_attrs(self): # should still make attrs list when attrs=None top = Topology() assert hasattr(top, 'attrs') assert isinstance(top.attrs, list)
def top(self, names, types, resids, resnames): return Topology(n_atoms=3, n_res=1, attrs=[names, types, resids, resnames])
def parse(self): """ Access ESPResSo data and return the topology object. Returns ------- top : :class:`MDAnalysis.core.topology.Topology` a topology object """ espresso = self.kwargs['espresso'] names = [] atomtypes = [] masses = [] charges = [] bonds = [] angles = [] dihedrals = [] for p in espresso.part: names.append("A" + repr(p.type)) atomtypes.append("T" + repr(p.type)) masses.append(p.mass) charges.append(p.q) for bond in p.bonds: partner_ids = bond[1:] n_partner = len(partner_ids) if n_partner == 1: bonds.append((p.id, partner_ids[0])) elif n_partner == 2: angles.append((partner_ids[0], p.id, partner_ids[1])) elif n_partner == 3: dihedrals.append( (partner_ids[0], p.id, partner_ids[1], partner_ids[2])) else: continue natoms = len(espresso.part) attrs = [ Atomnames(np.array(names, dtype=object)), Atomids(np.arange(natoms) + 1), Atomtypes(np.array(atomtypes, dtype=object)), Masses(masses), Resids(np.array([1])), Resnums(np.array([1])), Segids(np.array(['System'], dtype=object)), AltLocs(np.array([' '] * natoms, dtype=object)), Resnames(np.array(['R'], dtype=object)), Occupancies(np.zeros(natoms)), Tempfactors(np.zeros(natoms)), ICodes(np.array([' '], dtype=object)), Charges(np.array(charges)), Bonds(bonds), Angles(angles), Dihedrals(dihedrals) ] top = Topology(natoms, 1, 1, attrs=attrs) return top