def from_structure(cls, struct, term_decorate=True): """ Instantiates a ResidueTemplateContainer from a Structure instance filled with residues Parameters ---------- struct : :class:`parmed.structure.Structure` The structure from which to generate the ResidueTemplateContainer from term_decorate : bool, optional If True, terminal amino and nucleic acid residues will be adorned as follows: * N-prepended if it is an N-terminal amino acid * C-prepended if it is a C-terminal amino acid * 5-appended if it is a 5'-terminal nucleic acid * 3-appended if it is a 3'-terminal nucleic acid For example, an N-terminal GLY will become NGLY, while a 5'-terminal DA will become DA5. Default is True """ inst = cls() for res in struct.residues: rt = ResidueTemplate.from_residue(res) # See if we need to decorate the termini names if rt.head is None and rt.tail is not None and term_decorate: if AminoAcidResidue.has(rt.name): if len(rt.name) != 4 or rt.name[0] != 'N': rt.name = 'N%s' % rt.name elif RNAResidue.has(rt.name) or DNAResidue.has(rt.name): if rt.name[-1] != '5': rt.name = '%s5' % rt.name elif rt.tail is None and rt.head is not None and term_decorate: if AminoAcidResidue.has(rt.name): if len(rt.name) != 4 or rt.name[0] != 'C': rt.name = 'C%s' % rt.name elif RNAResidue.has(rt.name) or DNAResidue.has(rt.name): if rt.name[-1] != '3': rt.name = '%s3' % rt.name inst.append(rt) inst.box = struct.box return inst
def write(struct, dest, mol3=False, split=False): """ Writes a mol2 file from a structure or residue template Parameters ---------- struct : :class:`Structure` or :class:`ResidueTemplate` or :class:`ResidueTemplateContainer` The input structure to write the mol2 file from dest : str or file-like obj Name of the file to write or open file handle to write to mol3 : bool, optional If True and ``struct`` is a ResidueTemplate or container, write HEAD/TAIL sections. Default is False split : bool, optional If True and ``struct`` is a ResidueTemplateContainer or a Structure with multiple residues, each residue is printed in a separate @<MOLECULE> section that appear sequentially in the output file """ own_handle = False if not hasattr(dest, 'write'): own_handle = True dest = genopen(dest, 'w') if split: # Write sequentially if it is a multi-residue container or Structure if isinstance(struct, ResidueTemplateContainer): for res in struct: Mol2File.write(res, dest, mol3) return elif isinstance(struct, Structure) and len(struct.residues) > 1: for res in ResidueTemplateContainer.from_structure(struct): Mol2File.write(res, dest, mol3) return try: if isinstance(struct, ResidueTemplateContainer): natom = sum([len(c) for c in struct]) # To find the number of bonds, we need to total number of bonds # + the number of bonds that would be formed by "stitching" # together residues via their head and tail bonds = [] charges = [] bases = [1 for res in struct] for i, res in enumerate(struct): if i < len(struct) - 1: bases[i+1] = bases[i] + len(res) for i, res in enumerate(struct): for bond in res.bonds: bonds.append((bond.atom1.idx+bases[i], bond.atom2.idx+bases[i])) if i < len(struct)-1 and (res.tail is not None and struct[i+1].head is not None): bonds.append((res.tail.idx+bases[i], struct[i+1].head.idx+bases[i+1])) charges.extend([a.charge for a in res]) residues = struct if not struct.name: name = struct[0].name else: name = struct.name else: natom = len(struct.atoms) bonds = [(b.atom1.idx+1, b.atom2.idx+1) for b in struct.bonds] if isinstance(struct, ResidueTemplate): residues = [struct] name = struct.name else: residues = struct.residues name = struct.residues[0].name charges = [a.charge for a in struct.atoms] dest.write('@<TRIPOS>MOLECULE\n') dest.write('%s' % name) dest.write('\n') dest.write('%d %d %d 0 1\n' % (natom, len(bonds), len(residues))) if len(residues) == 1: dest.write('SMALL\n') else: for residue in residues: if AminoAcidResidue.has(residue.name): dest.write('PROTEIN\n') break if (RNAResidue.has(residue.name) or DNAResidue.has(residue.name)): dest.write('NUCLEIC\n') break else: dest.write('BIOPOLYMER\n') if not any(charges): dest.write('NO_CHARGES\n') printchg = False else: dest.write('USER_CHARGES\n') printchg = True # Now do ATOM section dest.write('@<TRIPOS>ATOM\n') j = 1 for i, res in enumerate(residues): for atom in res: try: x = atom.xx except AttributeError: x = 0 try: y = atom.xy except AttributeError: y = 0 try: z = atom.xz except AttributeError: z = 0 dest.write('%8d %-8s %10.4f %10.4f %10.4f %-8s %6d %-8s' % ( j, atom.name, x, y, z, atom.type.strip() or atom.name, i+1, res.name)) if printchg: dest.write(' %10.6f\n' % atom.charge) else: dest.write('\n') j += 1 dest.write('@<TRIPOS>BOND\n') for i, bond in enumerate(bonds): dest.write('%8d %8d %8d 1\n' % (i+1, bond[0], bond[1])) dest.write('@<TRIPOS>SUBSTRUCTURE\n') first_atom = 0 for i, res in enumerate(residues): if not hasattr(res, 'chain') or not res.chain: chain = '****' else: chain = res.chain intresbonds = 0 if isinstance(res, ResidueTemplate): if i != len(residues)-1 and (res.tail is not None and residues[i+1].head is not None): intresbonds += 1 if i != 0 and (res.head is not None and residues[i-1].tail is not None): intresbonds += 1 else: for atom in res: for a2 in atom.bond_partners: if a2.residue is not res: intresbonds += 1 dest.write('%8d %-8s %8d RESIDUE %4d %-4s ROOT %6d\n' % (i+1, res.name, first_atom+1, 0, chain[:4], intresbonds)) first_atom += len(res) if mol3: dest.write('@<TRIPOS>HEADTAIL\n') for i, res in enumerate(residues): if isinstance(res, ResidueTemplate): if res.head is not None: dest.write('%s %d\n' % (res.head.name, i+1)) else: dest.write('0 0\n') if res.tail is not None: dest.write('%s %d\n' % (res.tail.name, i+1)) else: dest.write('0 0\n') else: head = tail = None for atom in res: for a2 in atom.bond_partners: if a2.residue.idx == res.idx - 1: head = atom if a2.residue.idx == res.idx + 1: tail = atom if head is not None: dest.write('%s %d\n' % (head.name, i+1)) else: dest.write('0 0\n') if tail is not None: dest.write('%s %d\n' % (tail.name, i+1)) else: dest.write('0 0\n') dest.write('@<TRIPOS>RESIDUECONNECT\n') for i, res in enumerate(residues): if isinstance(res, ResidueTemplate): con = [res.head, res.tail, None, None, None, None] for i, a in enumerate(res.connections): con[i+2] = a else: con = [None, None, None, None, None, None] ncon = 2 for atom in res: for a2 in atom.bond_partners: if a2.residue.idx == res.idx - 1: con[0] = atom elif a2.residue.idx == res.idx + 1: con[1] = atom elif a2.residue.idx != res.idx: con[ncon] = atom ncon += 1 dest.write('%d' % (i+1)) for a in con: if a is not None: dest.write(' %s' % a.name) else: dest.write(' 0') dest.write('\n') finally: if own_handle: dest.close()
def write(struct, dest, mol3=False, split=False): """ Writes a mol2 file from a structure or residue template Parameters ---------- struct : :class:`Structure` or :class:`ResidueTemplate` or :class:`ResidueTemplateContainer` The input structure to write the mol2 file from dest : str or file-like obj Name of the file to write or open file handle to write to mol3 : bool, optional If True and ``struct`` is a ResidueTemplate or container, write HEAD/TAIL sections. Default is False split : bool, optional If True and ``struct`` is a ResidueTemplateContainer or a Structure with multiple residues, each residue is printed in a separate @<MOLECULE> section that appear sequentially in the output file """ own_handle = False if not hasattr(dest, 'write'): own_handle = True dest = genopen(dest, 'w') if split: # Write sequentially if it is a multi-residue container or Structure if isinstance(struct, ResidueTemplateContainer): try: for res in struct: Mol2File.write(res, dest, mol3) finally: if own_handle: dest.close() return elif isinstance(struct, Structure) and len(struct.residues) > 1: try: for res in ResidueTemplateContainer.from_structure(struct): Mol2File.write(res, dest, mol3) finally: if own_handle: dest.close() return try: if isinstance(struct, ResidueTemplateContainer): natom = sum([len(c) for c in struct]) # To find the number of bonds, we need to total number of bonds # + the number of bonds that would be formed by "stitching" # together residues via their head and tail bonds = [] charges = [] bases = [1 for res in struct] for i, res in enumerate(struct): if i < len(struct) - 1: bases[i+1] = bases[i] + len(res) for i, res in enumerate(struct): for bond in res.bonds: bonds.append((bond.atom1.idx+bases[i], bond.atom2.idx+bases[i])) if i < len(struct)-1 and (res.tail is not None and struct[i+1].head is not None): bonds.append((res.tail.idx+bases[i], struct[i+1].head.idx+bases[i+1])) charges.extend([a.charge for a in res]) residues = struct name = struct.name or struct[0].name else: natom = len(struct.atoms) bonds = [(b.atom1.idx+1, b.atom2.idx+1) for b in struct.bonds] if isinstance(struct, ResidueTemplate): residues = [struct] name = struct.name else: residues = struct.residues name = struct.residues[0].name charges = [a.charge for a in struct.atoms] dest.write('@<TRIPOS>MOLECULE\n') dest.write('%s\n' % name) dest.write('%d %d %d 0 1\n' % (natom, len(bonds), len(residues))) if len(residues) == 1: dest.write('SMALL\n') else: for residue in residues: if AminoAcidResidue.has(residue.name): dest.write('PROTEIN\n') break if (RNAResidue.has(residue.name) or DNAResidue.has(residue.name)): dest.write('NUCLEIC\n') break else: dest.write('BIOPOLYMER\n') if not any(charges): dest.write('NO_CHARGES\n') printchg = False else: dest.write('USER_CHARGES\n') printchg = True # See if we want to print box info if hasattr(struct, 'box') and struct.box is not None: box = struct.box dest.write('@<TRIPOS>CRYSIN\n') dest.write('%10.4f %10.4f %10.4f %10.4f %10.4f %10.4f 1 1\n' % (box[0], box[1], box[2], box[3], box[4], box[5])) # Now do ATOM section dest.write('@<TRIPOS>ATOM\n') j = 1 for i, res in enumerate(residues): for atom in res: try: x = atom.xx except AttributeError: x = 0 try: y = atom.xy except AttributeError: y = 0 try: z = atom.xz except AttributeError: z = 0 dest.write('%8d %-8s %10.4f %10.4f %10.4f %-8s %6d %-8s' % ( j, atom.name, x, y, z, atom.type.strip() or atom.name, i+1, res.name)) if printchg: dest.write(' %10.6f\n' % atom.charge) else: dest.write('\n') j += 1 dest.write('@<TRIPOS>BOND\n') for i, bond in enumerate(bonds): dest.write('%8d %8d %8d 1\n' % (i+1, bond[0], bond[1])) dest.write('@<TRIPOS>SUBSTRUCTURE\n') first_atom = 0 for i, res in enumerate(residues): if not hasattr(res, 'chain') or not res.chain: chain = '****' else: chain = res.chain intresbonds = 0 if isinstance(res, ResidueTemplate): if i != len(residues)-1 and (res.tail is not None and residues[i+1].head is not None): intresbonds += 1 if i != 0 and (res.head is not None and residues[i-1].tail is not None): intresbonds += 1 else: for atom in res: for a2 in atom.bond_partners: if a2.residue is not res: intresbonds += 1 dest.write('%8d %-8s %8d RESIDUE %4d %-4s ROOT %6d\n' % (i+1, res.name, first_atom+1, 0, chain[:4], intresbonds)) first_atom += len(res) if mol3: dest.write('@<TRIPOS>HEADTAIL\n') for i, res in enumerate(residues): if isinstance(res, ResidueTemplate): if res.head is not None: dest.write('%s %d\n' % (res.head.name, i+1)) else: dest.write('0 0\n') if res.tail is not None: dest.write('%s %d\n' % (res.tail.name, i+1)) else: dest.write('0 0\n') else: head = tail = None for atom in res: for a2 in atom.bond_partners: if a2.residue.idx == res.idx - 1: head = atom if a2.residue.idx == res.idx + 1: tail = atom if head is not None: dest.write('%s %d\n' % (head.name, i+1)) else: dest.write('0 0\n') if tail is not None: dest.write('%s %d\n' % (tail.name, i+1)) else: dest.write('0 0\n') dest.write('@<TRIPOS>RESIDUECONNECT\n') for i, res in enumerate(residues): if isinstance(res, ResidueTemplate): con = [res.head, res.tail, None, None, None, None] for i, a in enumerate(res.connections): con[i+2] = a else: con = [None, None, None, None, None, None] ncon = 2 for atom in res: for a2 in atom.bond_partners: if a2.residue.idx == res.idx - 1: con[0] = atom elif a2.residue.idx == res.idx + 1: con[1] = atom elif a2.residue.idx != res.idx: con[ncon] = atom ncon += 1 dest.write('%d' % (i+1)) for a in con: if a is not None: dest.write(' %s' % a.name) else: dest.write(' 0') dest.write('\n') finally: if own_handle: dest.close()
def count_nures(parm): nnuc = 0 for res in parm.residues: if RNAResidue.has(res.name) or DNAResidue.has(res.name): nnuc += 1 return nnuc