def check_topology(self): self.section("topology") self.log("Number of Atoms: %d" % ilen(self.t.topology.atoms)) self.log("Number of Residues: %d" % ilen(self.t.topology.residues)) self.log("Number of Chains: %d" % ilen(self.t.topology.chains)) self.log("Residue names: %s" % str([r.name for r in self.t.topology.residues])) self.log("Unique atom names: %s" % np.unique([a.name for a in self.t.topology.atoms]))
def check_topology(self): self.section('topology') self.log('Number of Atoms: %d' % ilen(self.t.topology.atoms)) self.log('Number of Residues: %d' % ilen(self.t.topology.residues)) self.log('Number of Chains: %d' % ilen(self.t.topology.chains)) self.log('Residue names: %s' % str([r.name for r in self.t.topology.residues])) self.log('Unique atom names: %s' % np.unique([a.name for a in self.t.topology.atoms]))
def _topology_from_subset(topology, atom_indices): """Create a new topology that only contains the supplied indices Note ---- This really should be a copy constructor (class method) on Topology, but I want it to work on either the mdtraj topology OR the OpenMM topology. An inplace version for the topology object we have here is also available. Parameters ---------- topology : topology The base topology atom_indices : list([int]) The indices of the atoms to keep """ newTopology = Topology() old_atom_to_new_atom = {} for chain in topology._chains: newChain = newTopology.add_chain() for residue in chain._residues: resSeq = getattr(residue, 'resSeq', None) or residue.index newResidue = newTopology.add_residue(residue.name, newChain, resSeq) for atom in residue._atoms: if atom.index in atom_indices: try: # OpenMM Topology objects don't have serial attributes, so we have to check first. serial = atom.serial except AttributeError: serial = None newAtom = newTopology.add_atom(atom.name, atom.element, newResidue, serial=serial) old_atom_to_new_atom[atom] = newAtom bondsiter = topology.bonds if not hasattr(bondsiter, '__iter__'): bondsiter = bondsiter() for atom1, atom2 in bondsiter: try: newTopology.add_bond(old_atom_to_new_atom[atom1], old_atom_to_new_atom[atom2]) except KeyError: pass # we only put bonds into the new topology if both of their partners # were indexed and thus HAVE a new atom # Delete empty residues for chain in newTopology._chains: chain._residues = [r for r in chain._residues if len(r._atoms) > 0] # Delete empty chains newTopology._chains = [c for c in newTopology._chains if len(c._residues) > 0] # Re-set the numAtoms and numResidues newTopology._numAtoms = ilen(newTopology.atoms) newTopology._numResidues = ilen(newTopology.residues) return newTopology
def check_topology(self): self.section("topology") self.log("Number of Atoms: %d" % ilen(self.topology.atoms)) self.log("Number of Residues: %d" % ilen(self.topology.residues)) self.log("Number of Chains: %d" % ilen(self.topology.chains)) self.log( "Residues: %s" % ", ".join(["%s (%d atoms)" % (r, ilen(r.atoms)) for r in self.topology.residues]) ) self.log("Unique atom names: %s" % ", ".join(np.unique([a.name for a in self.topology.atoms])))
def check_topology(self): self.section('topology') self.log('Number of Atoms: %d' % ilen(self.topology.atoms)) self.log('Number of Residues: %d' % ilen(self.topology.residues)) self.log('Number of Chains: %d' % ilen(self.topology.chains)) self.log('Residues: %s' % ', '.join([ '%s (%d atoms)' % (r, ilen(r.atoms)) for r in self.topology.residues ])) self.log('Unique atom names: %s' % ', '.join(np.unique([a.name for a in self.topology.atoms])))
def test_load_multiframe(): with open(get_fn('multiframe.pdb')) as f: pdb = PdbStructure(f) yield lambda: eq(len(pdb.models), 2) yield lambda: eq(len(pdb.models[0].chains), 1) yield lambda: eq(len(pdb.models[0].chains[0].residues), 3) yield lambda: eq(ilen(pdb.models[0].iter_atoms()), 22) yield lambda: eq(len(pdb.models[1].chains), 1) yield lambda: eq(len(pdb.models[1].chains[0].residues), 3) yield lambda: eq(ilen(pdb.models[1].iter_atoms()), 22) t = load(get_fn('multiframe.pdb')) yield lambda: eq(t.n_frames, 2) yield lambda: eq(t.n_atoms, 22) yield lambda: eq(t.xyz[0], t.xyz[1])
def test_legacy_hdf1(): t0 = load(fn, chunk=1) t1 = load(fn, chunk=10) t2 = load(fn, chunk=100) yield lambda: eq(t0.xyz, t1.xyz) yield lambda: eq(t0.xyz, t2.xyz) yield lambda: t0.topology == load(nat).topology yield lambda: eq(ilen(t0.topology.bonds), 14)
def write(self, positions, topology, modelIndex=None, unitcell_lengths=None, unitcell_angles=None, bfactors=None): """Write a PDB file to disk Parameters ---------- positions : array_like The list of atomic positions to write. topology : mdtraj.Topology The Topology defining the model to write. modelIndex : {int, None} If not None, the model will be surrounded by MODEL/ENDMDL records with this index unitcell_lengths : {tuple, None} Lengths of the three unit cell vectors, or None for a non-periodic system unitcell_angles : {tuple, None} Angles between the three unit cell vectors, or None for a non-periodic system bfactors : array_like, default=None, shape=(n_atoms,) Save bfactors with pdb file. Should contain a single number for each atom in the topology """ if not self._mode == 'w': raise ValueError('file not opened for writing') if not self._header_written: self._write_header(unitcell_lengths, unitcell_angles) self._header_written = True if ilen(topology.atoms) != len(positions): raise ValueError('The number of positions must match the number of atoms') if np.any(np.isnan(positions)): raise ValueError('Particle position is NaN') if np.any(np.isinf(positions)): raise ValueError('Particle position is infinite') self._last_topology = topology # Hack to save the topology of the last frame written, allows us to output CONECT entries in write_footer() if bfactors is None: bfactors = ['{0:5.2f}'.format(0.0)] * len(positions) else: if (np.max(bfactors) >= 100) or (np.min(bfactors) <= -10): raise ValueError("bfactors must be in (-10, 100)") bfactors = ['{0:5.2f}'.format(b) for b in bfactors] atomIndex = 1 posIndex = 0 if modelIndex is not None: print("MODEL %4d" % modelIndex, file=self._file) for (chainIndex, chain) in enumerate(topology.chains): chainName = self._chain_names[chainIndex % len(self._chain_names)] residues = list(chain.residues) for (resIndex, res) in enumerate(residues): if len(res.name) > 3: resName = res.name[:3] else: resName = res.name for atom in res.atoms: if len(atom.name) < 4 and atom.name[:1].isalpha() and (atom.element is None or len(atom.element.symbol) < 2): atomName = ' '+atom.name elif len(atom.name) > 4: atomName = atom.name[:4] else: atomName = atom.name coords = positions[posIndex] if atom.element is not None: symbol = atom.element.symbol else: symbol = ' ' line = "ATOM %5d %-4s %3s %s%4d %s%s%s 1.00 %s %2s " % ( atomIndex % 100000, atomName, resName, chainName, (res.resSeq) % 10000, _format_83(coords[0]), _format_83(coords[1]), _format_83(coords[2]), bfactors[posIndex], symbol) assert len(line) == 80, 'Fixed width overflow detected' print(line, file=self._file) posIndex += 1 atomIndex += 1 if resIndex == len(residues)-1: print("TER %5d %3s %s%4d" % (atomIndex, resName, chainName, res.resSeq), file=self._file) atomIndex += 1 if modelIndex is not None: print("ENDMDL", file=self._file)
def test_2EQQ_0(): # this is an nmr structure with 20 models t = load(get_fn('2EQQ.pdb')) yield lambda: eq(t.n_frames, 20) yield lambda: eq(t.n_atoms, 423) yield lambda: eq(ilen(t.top.residues), 28)
def extract(item, atom_indices='all', copy_if_all=True, check=True): if check: digest_item(item, 'mdtraj.Topology') atom_indices = digest_atom_indices(atom_indices) if atom_indices is 'all': if copy_if_all: from copy import deepcopy tmp_item = deepcopy(item) else: tmp_item = item else: from mdtraj.core.topology import Topology from mdtraj.utils import ilen atom_indices_to_be_kept = set(atom_indices) newTopology = Topology() old_atom_to_new_atom = {} for chain in item._chains: newChain = newTopology.add_chain() for group in chain._groups: resSeq = getattr(group, 'resSeq', None) or group.index newResidue = newTopology.add_group(group.name, newChain, resSeq, group.segment_id) for atom in group._atoms: if atom.index in atom_indices_to_be_kept: try: # OpenMM Topology objects don't have serial attributes, so we have to check first. serial = atom.serial except AttributeError: serial = None newAtom = newTopology.add_atom(atom.name, atom.element, newResidue, serial=serial) old_atom_to_new_atom[atom] = newAtom bondsiter = item.bonds if not hasattr(bondsiter, '__iter__'): bondsiter = bondsiter() for bond in bondsiter: try: atom1, atom2 = bond newTopology.add_bond(old_atom_to_new_atom[atom1], old_atom_to_new_atom[atom2], type=bond.type, order=bond.order) except KeyError: pass # we only put bonds into the new topology if both of their partners # were indexed and thus HAVE a new atom # Delete empty groups newTopology._groups = [ r for r in newTopology._groups if len(r._atoms) > 0 ] for chain in newTopology._chains: chain._groups = [r for r in chain._groups if len(r._atoms) > 0] # Delete empty chains newTopology._chains = [ c for c in newTopology._chains if len(c._groups) > 0 ] # Re-set the numAtoms and numResidues newTopology._numAtoms = ilen(newTopology.atoms) newTopology._numResidues = ilen(newTopology.groups) tmp_item = newTopology return tmp_item
def write(self, positions, topology, frame_ind=None, pcv_ind=None, unitcell_lengths=None, unitcell_angles=None): """Write a PDB file to disk using plumed2 PCV format Parameters ---------- positions : array_like The list of atomic positions to write. topology : mdtraj.Topology The Topology defining the model to write. frame_ind : {int, None} If not None, the index of frames will be surrounded by REMARK X=? and END unitcell_lengths : {tuple, None} Lengths of the three unit cell vectors, or None for a non-periodic system unitcell_angles : {tuple, None} Angles between the three unit cell vectors, or None for a non-periodic system """ if not self._mode == 'w': raise ValueError('file not opened for writing') if not self._header_written: self._write_header(unitcell_lengths, unitcell_angles) self._header_written = True if ilen(topology.atoms) != len(positions): raise ValueError('The number of positions must match the number of atoms') if np.any(np.isnan(positions)): raise ValueError('Particle position is NaN') if np.any(np.isinf(positions)): raise ValueError('Particle position is infinite') self._last_topology = topology # Hack to save the topology of the last frame written, allows us to output CONECT entries in write_footer() posIndex = 0 if frame_ind is not None: print("REMARK X=%d" % frame_ind, file=self._file) for (chainIndex, chain) in enumerate(topology.chains): chainName = self._chain_names[chainIndex % len(self._chain_names)] residues = list(chain.residues) for (resIndex, res) in enumerate(residues): if len(res.name) > 3: resName = res.name[:3] else: resName = res.name for atom in res.atoms: if len(atom.name) < 4 and atom.name[:1].isalpha() and ( atom.element is None or len(atom.element.symbol) < 2): atomName = ' ' + atom.name elif len(atom.name) > 4: atomName = atom.name[:4] else: atomName = atom.name coords = positions[posIndex] if atom.element is not None: symbol = atom.element.symbol else: symbol = ' ' line = "ATOM %5d %-4s %3s %1s%4d %s%s%s %5.2f %5.2f %-4s%-2s " % ( pcv_ind.atomInd[posIndex] % 100000, atomName, resName, chainName, (res.resSeq) % 10000, _format_83(coords[0]), _format_83(coords[1]), _format_83(coords[2]), pcv_ind.alignPLU[posIndex], pcv_ind.rmsPLU[posIndex], atom.segment_id[:4], symbol[-2:]) assert len(line) == 80, 'Fixed width overflow detected' print(line, file=self._file) posIndex += 1 if resIndex == len(residues) - 1: print("END", file=self._file)
def n_bonds(self): """Number of bonds in which the atom participates.""" # TODO: this info could be cached. return ilen(bond for bond in self.residue.chain.topology.bonds if self in bond)