def from_parmed(structure, refer_type=True): """Convert a parmed.Structure to a gmso.Topology. Convert a parametrized or un-parametrized parmed.Structure object to a topology.Topology. Specifically, this method maps Structure to Topology and Atom to Site. At this point, this method can only convert AtomType, BondType and AngleType. Conversion of DihedralType will be implement in the near future. Parameters ---------- structure : parmed.Structure parmed.Structure instance that need to be converted. refer_type : bool, optional, default=True Whether or not to transfer AtomType, BondType, AngleType, and DihedralType information Returns ------- top : gmso.Topology """ msg = "Provided argument is not a Parmed Structure" assert isinstance(structure, pmd.Structure), msg top = gmso.Topology(name=structure.title) site_map = dict() if np.all(structure.box): # This is if we choose for topology to have abox top.box = gmso.Box( (structure.box[0:3] * u.angstrom).in_units(u.nm), angles=u.degree * structure.box[3:6], ) # TO DO: come up with a solution to deal with partially parametrized # Parmed Structure # Old code: # simple check if our pmd.Structure is fully parametrized # is_parametrized = True if (isinstance(structure.atoms[i].atom_type, # pmd.AtomType) for i in range(len(structure.atoms))) else False # Consolidate parmed atomtypes and relate topology atomtypes if refer_type: pmd_top_atomtypes = _atom_types_from_pmd(structure) # Consolidate parmed bondtypes and relate to topology bondtypes bond_types_map = _get_types_map(structure, "bonds") pmd_top_bondtypes = _bond_types_from_pmd( structure, bond_types_members_map=bond_types_map ) # Consolidate parmed angletypes and relate to topology angletypes angle_types_map = _get_types_map(structure, "angles") pmd_top_angletypes = _angle_types_from_pmd( structure, angle_types_member_map=angle_types_map ) # Consolidate parmed dihedraltypes and relate to topology dihedraltypes dihedral_types_map = _get_types_map(structure, "dihedrals") dihedral_types_map.update(_get_types_map(structure, "rb_torsions")) pmd_top_dihedraltypes = _dihedral_types_from_pmd( structure, dihedral_types_member_map=dihedral_types_map ) subtops = list() for residue in structure.residues: subtop_name = ("{}[{}]").format(residue.name, residue.idx) subtops.append(gmso.SubTopology(name=subtop_name, parent=top)) for atom in residue.atoms: if refer_type and isinstance(atom.atom_type, pmd.AtomType): site = gmso.Atom( name=atom.name, charge=atom.charge * u.elementary_charge, position=( [atom.xx, atom.xy, atom.xz] * u.angstrom ).in_units(u.nm), atom_type=pmd_top_atomtypes[atom.atom_type], ) else: site = gmso.Atom( name=atom.name, charge=atom.charge * u.elementary_charge, position=( [atom.xx, atom.xy, atom.xz] * u.angstrom ).in_units(u.nm), atom_type=None, ) site_map[atom] = site subtops[-1].add_site(site) top.add_subtopology(subtops[-1]) for bond in structure.bonds: # Generate bond parameters for BondType that gets passed # to Bond if refer_type and isinstance(bond.type, pmd.BondType): top_connection = gmso.Bond( connection_members=[site_map[bond.atom1], site_map[bond.atom2]], bond_type=pmd_top_bondtypes[bond.type], ) # No bond parameters, make Connection with no connection_type else: top_connection = gmso.Bond( connection_members=[site_map[bond.atom1], site_map[bond.atom2]], bond_type=None, ) top.add_connection(top_connection, update_types=False) top.update_topology() for angle in structure.angles: # Generate angle parameters for AngleType that gets passed # to Angle if refer_type and isinstance(angle.type, pmd.AngleType): top_connection = gmso.Angle( connection_members=[ site_map[angle.atom1], site_map[angle.atom2], site_map[angle.atom3], ], angle_type=pmd_top_angletypes[angle.type], ) # No bond parameters, make Connection with no connection_type else: top_connection = gmso.Angle( connection_members=[ site_map[angle.atom1], site_map[angle.atom2], site_map[angle.atom3], ], angle_type=None, ) top.add_connection(top_connection, update_types=False) for dihedral in structure.dihedrals: # Generate dihedral parameters for DihedralType that gets passed # to Dihedral # These all follow periodic torsions functions # (even if they are improper dihedrals) # Which are the default expression in top.DihedralType # These periodic torsion dihedrals get stored in top.dihedrals if dihedral.improper: warnings.warn( "ParmEd improper dihedral {} ".format(dihedral) + "following periodic torsion " + "expression detected, currently accounted for as " + "topology.Dihedral with a periodic torsion expression" ) if refer_type and isinstance(dihedral.type, pmd.DihedralType): top_connection = gmso.Dihedral( connection_members=[ site_map[dihedral.atom1], site_map[dihedral.atom2], site_map[dihedral.atom3], site_map[dihedral.atom4], ], dihedral_type=pmd_top_dihedraltypes[dihedral.type], ) # No bond parameters, make Connection with no connection_type else: top_connection = gmso.Dihedral( connection_members=[ site_map[dihedral.atom1], site_map[dihedral.atom2], site_map[dihedral.atom3], site_map[dihedral.atom4], ], dihedral_type=None, ) top.add_connection(top_connection, update_types=False) for rb_torsion in structure.rb_torsions: # Generate dihedral parameters for DihedralType that gets passed # to Dihedral # These all follow RB torsion functions # These RB torsion dihedrals get stored in top.dihedrals if rb_torsion.improper: warnings.warn( "ParmEd improper dihedral {} ".format(rb_torsion) + "following RB torsion " + "expression detected, currently accounted for as " + "topology.Dihedral with a RB torsion expression" ) if refer_type and isinstance(rb_torsion.type, pmd.RBTorsionType): top_connection = gmso.Dihedral( connection_members=[ site_map[rb_torsion.atom1], site_map[rb_torsion.atom2], site_map[rb_torsion.atom3], site_map[rb_torsion.atom4], ], dihedral_type=pmd_top_dihedraltypes[rb_torsion.type], ) # No bond parameters, make Connection with no connection_type else: top_connection = gmso.Dihedral( connection_members=[ site_map[rb_torsion.atom1], site_map[rb_torsion.atom2], site_map[rb_torsion.atom3], site_map[rb_torsion.atom4], ], dihedral_type=None, ) top.add_connection(top_connection, update_types=False) top.update_topology() top.combining_rule = structure.combining_rule return top
def from_parmed(structure): """Convert a parmed.Structure to a gmso.Topology Convert a parametrized or un-parametrized parmed.Structure object to a topology.Topology. Specifically, this method maps Structure to Topology and Atom to Site. At this point, this method can only convert AtomType, BondType and AngleType. Conversion of DihedralType will be implement in the near future. Parameters ---------- structure : parmed.Structure parmed.Structure instance that need to be converted. Returns ------- top : gmso.Topology """ msg = ("Provided argument that is not a Parmed Structure") assert isinstance(structure, pmd.Structure), msg top = gmso.Topology(name=structure.title) site_map = dict() for atom in structure.atoms: if isinstance(atom.atom_type, pmd.AtomType): atom_type = gmso.AtomType( name=atom.atom_type.name, charge=atom.atom_type.charge * u.elementary_charge, parameters={ 'sigma': (atom.sigma * u.angstrom).in_units(u.nm), 'epsilon': atom.epsilon * u.Unit('kcal / mol') }) site = gmso.Site( name=atom.name, charge=atom.charge * u.elementary_charge, position=([atom.xx, atom.xy, atom.xz] * u.angstrom).in_units( u.nm), atom_type=atom_type) else: site = gmso.Site( name=atom.name, charge=atom.charge * u.elementary_charge, position=([atom.xx, atom.xy, atom.xz] * u.angstrom).in_units( u.nm), atom_type=None) site_map[atom] = site top.add_site(site) top.update_topology() if np.all(structure.box): # This is if we choose for topology to have abox top.box = gmso.Box( (structure.box[0:3] * u.angstrom).in_units(u.nm), angles=u.degree * structure.box[3:6]) for bond in structure.bonds: # Generate bond parameters for BondType that gets passed # to Bond if isinstance(bond.type, pmd.BondType): bond_params = { 'k': (2 * bond.type.k * u.Unit('kcal / (nm**2 * mol)')), 'r_eq': (bond.type.req * u.angstrom).in_units(u.nm) } new_connection_type = gmso.BondType(parameters=bond_params) top_connection = gmso.Bond(connection_members=[site_map[bond.atom1], site_map[bond.atom2]], connection_type=new_connection_type) # No bond parameters, make Connection with no connection_type else: top_connection = gmso.Bond(connection_members=[site_map[bond.atom1], site_map[bond.atom2]], connection_type=None) top.add_connection(top_connection, update_types=False) top.update_topology() print(top.n_bonds) for angle in structure.angles: # Generate angle parameters for AngleType that gets passed # to Angle if isinstance(angle.type, pmd.AngleType): angle_params = { 'k': (2 * angle.type.k * u.Unit('kcal / (rad**2 * mol)')), 'theta_eq': (angle.type.theteq * u.degree) } new_connection_type = gmso.AngleType(parameters=angle_params) top_connection = gmso.Angle(connection_members=[site_map[angle.atom1], site_map[angle.atom2], site_map[angle.atom3]], connection_type=new_connection_type) # No bond parameters, make Connection with no connection_type else: top_connection = gmso.Angle(connection_members=[site_map[angle.atom1], site_map[angle.atom2], site_map[angle.atom3]], connection_type=None) top.add_connection(top_connection, update_types=False) top.update_topology() # TODO: Dihedrals return top