Esempio n. 1
0
def SaveITPFile(path, mol, pmol=None):
    print("Saving molecule %s to ITP file at path %s." %
          (mol.GetName(), str(os.path.join(os.getcwd(), path))))
    path = Path(path)
    h_mass = ix.GetPeriodicTable()["H"].GetAtomicMass()
    path.parent.mkdir(parents=True, exist_ok=True)
    file = path.open('w')
    # header printing
    header = """; File generated by the indigox package
; No guarantees are provided for the usefulness of this file
    
[ moleculetype ]
; Name  nrexcl
TEST   3
    
[ atoms ]"""
    print(header, file=file)

    # atom printing
    atm_fmt_str = "{index:>5} {type:>6} {residx:>5} {resname:>8} {name:>7} {chargegroup:>5} {charge:>11.5f} {mass:>9.4f}  {extra}"
    for atom in mol.GetAtoms():
        atm_dat = {
            "index": atom.GetIndex() + 1,
            "type": atom.GetType().GetName() if atom.HasType() else "%%%",
            "residx": atom.GetResidueID(),
            "resname": atom.GetResidueName(),
            "name": atom.GetName(),
            "chargegroup": atom.GetChargeGroupID() + 1,
            "charge": atom.GetPartialCharge(),
            "mass": atom.GetElement().GetAtomicMass() +
            atom.GetImplicitCount() * h_mass,
            "extra": ""
        }
        if pmol is not None:
            patom = pmol.GetAtom(atom)
            extra_info = ";"
            if not len(patom.GetMappedCharges()):
                extra_info += " UNMAPPED"
            else:
                mu = patom.MeanCharge()
                eta = patom.MedianCharge()
                sigma = patom.StandardDeviationCharge()
                delta = patom.RedistributedChargeAdded()
                to_add = []
                if round(mu, 5) != round(eta, 5) or round(sigma, 5) != 0.0:
                    to_add.append("mean: {:.5f}".format(mu))
                    to_add.append("median: {:.5f}".format(eta))
                    to_add.append("stdev: {:.5f}".format(sigma))
                if round(delta, 5) != 0.0:
                    to_add.append("added: {:.5f}".format(delta))
                extra_info += " " + ','.join(to_add)
            if extra_info == ";":
                atm_dat["extra"] = ""
            else:
                atm_dat["extra"] = extra_info
        print(atm_fmt_str.format(**atm_dat), file=file)

    # bond printing
    print("\n[ bonds ]", file=file)
    bnd_fmt_str = "{atoma:>5} {atomb:>5} {typecode:>5}    gb_{typeid}   {extra}"
    for bond in sorted(mol.GetBonds(), key=lambda x: x.HasType()):
        bnd_dat = {
            "atoma": bond.GetAtoms()[0].GetIndex() + 1,
            "atomb": bond.GetAtoms()[1].GetIndex() + 1,
            "typecode": 2,
            "typeid": bond.GetType().GetID() if bond.HasType() else "UNMAPPED"
        }
        if pmol is not None and bond.HasType():
            pbond = pmol.GetBond(bond)
            other = [
                "gb_{}".format(tm.GetID())
                for tm in pbond.GetMappedTypeCounts()
            ]
            bnd_dat["extra"] = ", ".join(
                x for x in other if x != "gb_{}".format(bnd_dat["typeid"]))
        else:
            bnd_dat["extra"] = ""
        if bnd_dat["extra"]:
            bnd_dat["extra"] = "; Other terms: " + bnd_dat["extra"]
        print(bnd_fmt_str.format(**bnd_dat), file=file)

    # pairs printing
    print("\n[ pairs ]", file=file)
    pair_fmt_str = "{atoma:>5} {atomb:>5}  1"
    for dhd in mol.GetDihedrals():
        atoms = dhd.GetAtoms()
        if not mol.HasBond(atoms[0], atoms[1]):
            continue
        if not mol.HasBond(atoms[1], atoms[2]):
            continue
        if not mol.HasBond(atoms[2], atoms[3]):
            continue

        if ((mol.GetBond(atoms[0], atoms[1]).GetOrder()
             == ix.BondOrder.Aromatic) and (mol.GetBond(
                 atoms[1], atoms[2]).GetOrder() == ix.BondOrder.Aromatic)
                and (mol.GetBond(atoms[2], atoms[3]).GetOrder()
                     == ix.BondOrder.Aromatic)):
            continue

        if atoms[0].GetIndex() > atoms[3].GetIndex():
            pair_dat = {
                "atoma": atoms[3].GetIndex() + 1,
                "atomb": atoms[0].GetIndex() + 1
            }
        else:
            pair_dat = {
                "atoma": atoms[0].GetIndex() + 1,
                "atomb": atoms[3].GetIndex() + 1
            }
        print(pair_fmt_str.format(**pair_dat), file=file)

    # angle printing
    print("\n[ angles ]", file=file)
    ang_fmt_str = "{atoma:>5} {atomb:>5} {atomc:>5} {typecode:>5}    ga_{typeid}   {extra}"
    for angle in sorted(mol.GetAngles(), key=lambda x: x.HasType()):
        atoms = angle.GetAtoms()
        ang_dat = {
            "atoma": atoms[0].GetIndex() + 1,
            "atomb": atoms[1].GetIndex() + 1,
            "atomc": atoms[2].GetIndex() + 1,
            "typecode": 2,
            "typeid":
            angle.GetType().GetID() if angle.HasType() else "UNMAPPED",
            "extra": ""
        }
        if pmol is not None and angle.HasType():
            pangle = pmol.GetAngle(angle)
            other = [
                "ga_{}".format(tm.GetID())
                for tm in pangle.GetMappedTypeCounts()
            ]
            ang_dat["extra"] = ", ".join(
                x for x in other if x != "ga_{}".format(ang_dat["typeid"]))
        if ang_dat["extra"]:
            ang_dat["extra"] = "; Other terms: " + ang_dat["extra"]
        print(ang_fmt_str.format(**ang_dat), file=file)

    # dihedral printing
    print("\n[ dihedrals ]", file=file)
    dhd_fmt_str = "{atoma:>5} {atomb:>5} {atomc:>5} {atomd:>5} {typecode:>5}    {typeid}    {extra}"
    done_dhds = []
    for bnd in mol.GetBonds():
        dhds = _GetBondDihedrals(bnd)
        if not dhds:
            continue
        param_dhd = [x for x in dhds if x.HasType()]
        if not param_dhd:
            done_dhds.append(dhds[0])
        else:
            done_dhds.extend(param_dhd)
    for dhd in mol.GetDihedrals():
        if dhd.HasType() and dhd not in done_dhds:
            done_dhds.append(dhd)
    for dhd in sorted(done_dhds, key=lambda x: x.HasType()):
        atoms = dhd.GetAtoms()
        if not dhd.HasType():
            dhd_dat = {
                "atoma": atoms[0].GetIndex() + 1,
                "atomb": atoms[1].GetIndex() + 1,
                "atomc": atoms[2].GetIndex() + 1,
                "atomd": atoms[3].GetIndex() + 1,
                "extra": "",
                "typecode": "",
                "typeid": "UNMAPPED"
            }
            print(dhd_fmt_str.format(**dhd_dat), file=file)
        else:
            for t in dhd.GetTypes():
                dhd_dat = {
                    "atoma": atoms[0].GetIndex() + 1,
                    "atomb": atoms[1].GetIndex() + 1,
                    "atomc": atoms[2].GetIndex() + 1,
                    "atomd": atoms[3].GetIndex() + 1,
                    "extra": ""
                }
                if t.GetType() == ix.DihedralType.Proper:
                    dhd_dat["typecode"] = 1
                    dhd_dat["typeid"] = "gd_{}".format(t.GetID())
                else:
                    dhd_dat["typecode"] = 2
                    dhd_dat["typeid"] = "gi_{}".format(t.GetID())
                print(dhd_fmt_str.format(**dhd_dat), file=file)
    file.close()
Esempio n. 2
0
def LoadIFPFile(path):
    pt = ix.GetPeriodicTable()
    data = list(ix.LoadFile(path.expanduser()))
    blocks = [data[0]]
    for i in range(len(data) - 1):
        if data[i] == 'END':
            blocks.append(data[i + 1])
    ff = ix.Forcefield(ix.FFFamily.GROMOS, path.stem)
    for b in blocks:
        start = data.index(b) + 1
        end = data[start:].index('END') + start
        if b == 'BONDSTRETCHTYPECODE':
            ff.ReserveBondTypes(ix.BondType.Harmonic,
                                int(data[start].split()[0]))
            ff.ReserveBondTypes(ix.BondType.Quartic,
                                int(data[start].split()[0]))
            for line in data[start + 1:end]:
                idx, kq, kh, b0 = map(float, line.split())
                ff.LinkBondTypes(
                    ff.NewBondType(ix.BondType.Harmonic, int(idx), kh, b0),
                    ff.NewBondType(ix.BondType.Quartic, int(idx), kq, b0))
        elif b == 'BONDANGLEBENDTYPECODE':
            ff.ReserveAngleTypes(ix.AngleType.Harmonic,
                                 int(data[start].split()[0]))
            ff.ReserveAngleTypes(ix.AngleType.CosineHarmonic,
                                 int(data[start].split()[0]))
            for line in data[start + 1:end]:
                idx, kch, kh, t0 = map(float, line.split())
                ff.LinkAngleTypes(
                    ff.NewAngleType(ix.AngleType.Harmonic, int(idx), kh, t0),
                    ff.NewAngleType(ix.AngleType.CosineHarmonic, int(idx), kch,
                                    t0))
        elif b == 'IMPDIHEDRALTYPECODE':
            ff.ReserveDihedralTypes(ix.DihedralType.Improper,
                                    int(data[start].split()[0]))
            for line in data[start + 1:end]:
                idx, k, epsilon = map(float, line.split())
                ff.NewDihedralType(ix.DihedralType.Improper, int(idx), k,
                                   epsilon)
        elif b == 'TORSDIHEDRALTYPECODE':
            ff.ReserveDihedralTypes(ix.DihedralType.Proper,
                                    int(data[start].split()[0]))
            for line in data[start + 1:end]:
                idx, k, phase, m = map(float, line.split())
                ff.NewDihedralType(ix.DihedralType.Proper, int(idx), k, phase,
                                   int(m))
        elif b == 'SINGLEATOMLJPAIR':
            num_lines = int((end - start - 1) / int(data[start]))
            atm_count = int(data[start])
            ff.ReserveAtomTypes(atm_count)
            for i in range(atm_count):
                lines = []
                for j in range(num_lines):
                    lines.append(data[start + 1 + j + i * num_lines])
                dat = "   ".join(x for x in lines).split()
                atm_dat = {
                    'int_code': int(dat[0]),
                    'name': dat[1],
                    'c6': float(dat[2])**2,
                    'c12': [
                        float(dat[3])**2,
                        float(dat[4])**2,
                        float(dat[5])**2,
                    ],
                    'c6_1_4': float(dat[6])**2,
                    'c12_1_4': float(dat[7])**2,
                    'interactions': dict(),
                }
                ff.NewAtomType(int(dat[0]), dat[1], pt[dat[1][0]])
    return ff
Esempio n. 3
0
def SaveRTPFile(path, mol, pmol=None):
    print("Saving molecule %s to RTP file at path %s." %
          (mol.GetName(), str(os.path.join(os.getcwd(), path))))
    path = Path(path)
    h_mass = ix.GetPeriodicTable()["H"].GetAtomicMass()
    path.parent.mkdir(parents=True, exist_ok=True)
    file = path.open('w')
    # header printing
    header = """; File generated by the indigox package
; No guarantees are provided for the usefulness of this file

[ {} ]
  [ atoms ]"""
    print(header.format(mol.GetAtoms()[0].GetResidueName()), file=file)

    # atom printing
    atm_fmt_str = "{name:>5} {type:>6} {charge:>11.5f} {chargegroup:>5} {extra}"
    for atom in mol.GetAtoms():
        atm_dat = {
            "type": atom.GetType().GetName() if atom.HasType() else "%%%",
            "name": atom.GetName(),
            "chargegroup": atom.GetChargeGroupID() + 1,
            "charge": atom.GetPartialCharge(),
            "extra": ""
        }
        if pmol is not None:
            patom = pmol.GetAtom(atom)
            extra_info = ";"
            if not len(patom.GetMappedCharges()):
                extra_info += " UNMAPPED"
            else:
                mu = patom.MeanCharge()
                eta = patom.MedianCharge()
                sigma = patom.StandardDeviationCharge()
                delta = patom.RedistributedChargeAdded()
                to_add = []
                if round(mu, 5) != round(eta, 5) or round(sigma, 5) != 0.0:
                    to_add.append("mean: {:.5f}".format(mu))
                    to_add.append("median: {:.5f}".format(eta))
                    to_add.append("stdev: {:.5f}".format(sigma))
                if round(delta, 5) != 0.0:
                    to_add.append("added: {:.5f}".format(delta))
                extra_info += " " + ", ".join(to_add)
            if extra_info == ";":
                atm_dat["extra"] = ""
            else:
                atm_dat["extra"] = extra_info
        print(atm_fmt_str.format(**atm_dat), file=file)

    # bond printing
    print("  [ bonds ]", file=file)
    bnd_fmt_str = "{atoma:>5} {atomb:>5}   {typeid}   {extra}"
    for bond in sorted(mol.GetBonds(), key=lambda x: x.HasType()):
        bnd_dat = {
            "atoma": bond.GetAtoms()[0].GetName(),
            "atomb": bond.GetAtoms()[1].GetName(),
            "extra": ""
        }
        if not bond.HasType(): bnd_dat["typeid"] = "UNMAPPED"
        else:
            t = bond.GetType()
            if t.GetType() != ix.BondType.Quartic: t = t.GetLinkedType()
            bnd_dat["typeid"] = "{:>.4f}  {:>.4e}".format(
                t.GetIdealLength(), t.GetForceConstant())
        if pmol is not None and bond.HasType():
            pbond = pmol.GetBond(bond)
            other = [
                "gb_{}".format(tm.GetID())
                for tm in pbond.GetMappedTypeCounts()
            ]
            bnd_dat["extra"] = ", ".join(
                x for x in other
                if x != "gb_{}".format(bond.GetType().GetID()))
        else:
            bnd_dat["extra"] = ""
        if bnd_dat["extra"]:
            bnd_dat["extra"] = "; Other terms: " + bnd_dat["extra"]
        print(bnd_fmt_str.format(**bnd_dat), file=file)

    # exclusions printing
    print("  [ exclusions ]", file=file)
    pair_fmt_str = "{atoma:>5} {atomb:>5}"
    for dhd in mol.GetDihedrals():
        atoms = dhd.GetAtoms()
        if not mol.HasBond(atoms[0], atoms[1]):
            continue
        if not mol.HasBond(atoms[1], atoms[2]):
            continue
        if not mol.HasBond(atoms[2], atoms[3]):
            continue

        rot_bond = mol.GetBond(atoms[1], atoms[2])
        if rot_bond.GetOrder() == ix.BondOrder.Aromatic:
            pair_dat = {
                "atoma": atoms[3].GetName(),
                "atomb": atoms[0].GetName()
            }
            print(pair_fmt_str.format(**pair_dat), file=file)

    # angle printing
    print("  [ angles ]", file=file)
    ang_fmt_str = "{atoma:>5} {atomb:>5} {atomc:>5}  {typeid}   {extra}"
    for angle in sorted(mol.GetAngles(), key=lambda x: x.HasType()):
        atoms = angle.GetAtoms()
        ang_dat = {
            "atoma": atoms[0].GetName(),
            "atomb": atoms[1].GetName(),
            "atomc": atoms[2].GetName(),
            "extra": ""
        }
        if not angle.HasType(): ang_dat["typeid"] = "UNMAPPED"
        else:
            t = angle.GetType()
            if t.GetType() != ix.AngleType.CosineHarmonic:
                t = t.GetLinkedType()
            ang_dat["typeid"] = "{:>.2f}  {:>.2f}".format(
                t.GetIdealAngle(), t.GetForceConstant())
        if pmol is not None and angle.HasType():
            pangle = pmol.GetAngle(angle)
            other = [
                "ga_{}".format(tm.GetID())
                for tm in pangle.GetMappedTypeCounts()
            ]
            ang_dat["extra"] = ", ".join(
                x for x in other
                if x != "ga_{}".format(angle.GetType().GetID()))
        if ang_dat["extra"]:
            ang_dat["extra"] = "; Other terms: " + ang_dat["extra"]
        print(ang_fmt_str.format(**ang_dat), file=file)

    # improper printing
    done_dhds = []
    print("  [ impropers ]", file=file)
    dhd_fmt_str = "{atoma:>5} {atomb:>5} {atomc:>5} {atomd:>5}  {typeid}  {extra}"
    for imp in mol.GetDihedrals():
        if not imp.HasType(): continue
        for t in imp.GetTypes():
            if t.GetType() != ix.DihedralType.Improper: continue
            atoms = imp.GetAtoms()
            imp_dat = {
                "atoma":
                atoms[0].GetName(),
                "atomb":
                atoms[1].GetName(),
                "atomc":
                atoms[2].GetName(),
                "atomd":
                atoms[3].GetName(),
                "typeid":
                "{:>.5f}   {:>.5f}".format(
                    t.GetIdealAngle(),
                    t.GetForceConstant() * improper_correction),
                "extra":
                ""
            }
            print(dhd_fmt_str.format(**imp_dat), file=file)

    # dihedral printing
    print("  [ dihedrals ]", file=file)
    for bnd in mol.GetBonds():
        dhds = _GetBondDihedrals(bnd)
        if not dhds: continue
        param_dhd = [x for x in dhds if x.HasType()]
        if not param_dhd: done_dhds.append(dhds[0])
        else: done_dhds.extend(param_dhd)
    for dhd in mol.GetDihedrals():
        if dhd.HasType() and dhd not in done_dhds: done_dhds.append(dhd)
    for dhd in sorted(done_dhds, key=lambda x: x.HasType()):
        atoms = dhd.GetAtoms()
        if not dhd.HasType():
            dhd_dat = {
                "atoma": atoms[0].GetName(),
                "atomb": atoms[1].GetName(),
                "atomc": atoms[2].GetName(),
                "atomd": atoms[3].GetName(),
                "extra": "",
                "typeid": "UNMAPPED"
            }
            print(dhd_fmt_str.format(**dhd_dat), file=file)
        else:
            for t in dhd.GetTypes():
                dhd_dat = {
                    "atoma": atoms[0].GetName(),
                    "atomb": atoms[1].GetName(),
                    "atomc": atoms[2].GetName(),
                    "atomd": atoms[3].GetName(),
                    "extra": ""
                }
                if t.GetType() == ix.DihedralType.Proper:
                    dhd_dat["typeid"] = "{:.4f}  {:.4f}  {}".format(
                        t.GetPhaseShift(), t.GetForceConstant(),
                        t.GetMultiplicity())
                    print(dhd_fmt_str.format(**dhd_dat), file=file)
    file.close()