def LoadFragmentFile(path, ff): file_data = list(ix.LoadFile(path.expanduser())) if file_data.count("MOLECULE") != 1: raise InputError("Expect only one molecule per file") if file_data[0] != "MOLECULE": raise InputError("Expected MOLECULE block") if file_data.count("FRAGMENT") != file_data.count("OVERLAP"): raise InputError("Should have same number of fragment and overlaps") if "END" in file_data[1:4]: raise InputError("Missing input files") coord_path = path.parent / file_data[1].strip() param_path = path.parent / file_data[2].strip() detail_path = path.parent / file_data[3].strip() mol = LoadParameterisedMolecule(coord_path, param_path, ff, detail_path) fragments = [] current_block = None frag = [] overlap = [] for line in file_data: if line == "END": if current_block == "OVERLAP": frag = ix.VecAtom(frag) overlap = ix.VecAtom(overlap) fragments.append(ix.Fragment(mol, frag, overlap)) frag = [] overlap = [] current_block = None elif line in ["MOLECULE", "FRAGMENT", "OVERLAP"]: current_block = line elif current_block == "FRAGMENT": frag.extend(mol.GetAtomTag(x) for x in map(int, line.split())) elif current_block == "OVERLAP": overlap.extend(mol.GetAtomTag(x) for x in map(int, line.split())) return mol, fragments
def LoadITPFile(path, ff, details=None): mol = ix.Molecule(path.stem) bondtype = ix.BondType.Harmonic angletype = ix.AngleType.Harmonic impropertype = ix.DihedralType.Improper propertype = ix.DihedralType.Proper current_block = None for line in ix.LoadFile(path.expanduser(), comment=";"): if "[" in line: data = line.split() current_block = data[1] elif "#" in line: current_block = None elif current_block == "atoms": data = line.split() atom = mol.NewAtom() atom.SetTag(int(data[0])) atom.SetName(data[4]) atom.SetType(ff.GetAtomType(data[1])) atom.SetPartialCharge(float(data[6])) atom.SetElement(atom.GetType().GetElement()) elif current_block == "bonds": data = line.split() bond = mol.NewBond(mol.GetAtomTag(int(data[0])), mol.GetAtomTag(int(data[1]))) if data[-1].startswith("gb"): bond.SetType( ff.GetBondType(bondtype, int(data[-1].split("_")[1]))) elif current_block == "angles": data = line.split() a1 = mol.GetAtomTag(int(data[0])) a2 = mol.GetAtomTag(int(data[1])) a3 = mol.GetAtomTag(int(data[2])) angle = mol.GetAngle(mol.GetAtomTag(int(data[0])), mol.GetAtomTag(int(data[1])), mol.GetAtomTag(int(data[2]))) if not angle: raise IndexError("No angle found: {}-{}-{}".format(*data[:3])) if data[-1].startswith("ga"): ty = ff.GetAngleType(angletype, int(data[-1].split("_")[1])) angle.SetType(ty) elif current_block == "dihedrals": data = line.split() a = mol.GetAtomTag(int(data[0])) b = mol.GetAtomTag(int(data[1])) c = mol.GetAtomTag(int(data[2])) d = mol.GetAtomTag(int(data[3])) if mol.HasDihedral(a, b, c, d): dihedral = mol.GetDihedral(a, b, c, d) else: dihedral = mol.NewDihedral(a, b, c, d) if data[-1].startswith("gi"): dihedral.AddType( ff.GetDihedralType(impropertype, int(data[-1].split("_")[1]))) elif data[-1].startswith("gd"): dihedral.AddType( ff.GetDihedralType(propertype, int(data[-1].split("_")[1]))) if details is not None: LoadIXDFile(details, mol) return mol
def LoadIXDFile(path, mol): set_implicits = [] for line in ix.LoadFile(path.expanduser()): line = line.split() l = list(map(int, line[1:])) if line[0] == "ATOM": atom = mol.GetAtomTag(l[0]) if not atom: raise IndexError("Unknown atom tag: {}".format(l[0])) atom.SetFormalCharge(l[1]) atom.SetImplicitCount(l[2]) set_implicits.append(l[0]) elif line[0] == "BOND": bond = mol.GetBond(mol.GetAtomTag(l[0]), mol.GetAtomTag(l[1])) if not bond: raise IndexError("Unknown bond: {}-{}".format(l[0], l[1])) if l[2] == 1: bond.SetOrder(ix.BondOrder.Single) elif l[2] == 2: bond.SetOrder(ix.BondOrder.Double) elif l[2] == 3: bond.SetOrder(ix.BondOrder.Triple) elif l[2] == 4: bond.SetOrder(ix.BondOrder.Quadruple) elif l[2] == 5: bond.SetOrder(ix.BondOrder.Aromatic) elif l[2] == 6: bond.SetOrder(ix.BondOrder.OneAndAHalf) elif l[2] == 7: bond.SetOrder(ix.BondOrder.TwoAndAHalf) elif line[0] == "MOLECULE": mol.SetMolecularCharge(l[0]) set_implicits = set(set_implicits) for atom in mol.GetAtoms(): if atom.GetElement() != "C": continue if atom.GetTag() in set_implicits: continue bonded_count = 0 aromatic_bonds = False for bond in atom.GetBonds(): if bond.GetOrder() == ix.BondOrder.Single: bonded_count += 1 elif bond.GetOrder() == ix.BondOrder.Double: bonded_count += 2 elif bond.GetOrder() == ix.BondOrder.Triple: bonded_count += 3 elif bond.GetOrder() == ix.BondOrder.Quadruple: bonded_count += 4 elif bond.GetOrder() == ix.BondOrder.Aromatic: if not aromatic_bonds: bonded_count += 1 aromatic_bonds = True bonded_count += 1 elif bond.GetOrder() == ix.BondOrder.OneAndAHalf: bonded_count += 1.5 elif bond.GetOrder() == ix.BondOrder.TwoAndAHalf: bonded_count += 2.5 if (((bonded_count - int(bonded_count)) != 0) or bonded_count > 4): raise ValueError("Atom tag {} has weird valence state.".format( atom.GetTag())) atom.SetImplicitCount(4 - bonded_count) tot_charge = sum(atm.GetFormalCharge() for atm in mol.GetAtoms()) if tot_charge != mol.GetMolecularCharge(): raise ValueError( "Sum of atom formal charges does not match molecular charge")
def LoadMTBFile(path, ff, details=None): file = list(ix.LoadFile(path.expanduser())) blocks = [file[0]] for i in range(len(file) - 1): if file[i] == "END" and len(file[i + 1]): blocks.append(file[i + 1]) mol = ix.Molecule(path.stem) bondtype = ix.BondType.Quartic angletype = ix.AngleType.CosineHarmonic impropertype = ix.DihedralType.Improper propertype = ix.DihedralType.Proper for b in blocks: start = file.index(b) + 1 if b == "MTBUILDBLSOLUTE": counts = [0, 0, 0, 0, 0, 0] start_line = [0, 0, 0, 0, 0, 0] mol.SetName(file[start]) for i in range(len(counts)): pre = start + 1 + len(counts[:i]) + sum(counts[:i]) counts[i] = int(file[pre].split()[0]) start_line[i] = pre + 1 for i in range(len(file)): dat = file[i].split() if i in (x - 1 for x in start_line) or i <= start: continue elif i < start_line[0] + counts[0]: # Atom data atom = mol.NewAtom() atom.SetTag(int(dat[0])) atom.SetName(dat[1]) atom.SetType(ff.GetAtomType(int(dat[2]))) atom.SetPartialCharge(float(dat[4])) atom.SetElement(atom.GetType().GetElement()) elif i < start_line[1] + counts[1]: # Bond data bond = mol.NewBond(mol.GetAtomTag(int(dat[0])), mol.GetAtomTag(int(dat[1]))) bond.SetType(ff.GetBondType(bondtype, int(dat[2]))) elif i < start_line[2] + counts[2]: # Angle data angle = mol.GetAngle(mol.GetAtomTag(int(dat[0])), mol.GetAtomTag(int(dat[1])), mol.GetAtomTag(int(dat[2]))) if not angle: raise IndexError( "No angle found: {}-{}-{}".format(*dat[:3])) angle.SetType(ff.GetAngleType(angletype, int(dat[3]))) elif i < start_line[3] + counts[3]: # Improper dihedrals a = mol.GetAtomTag(int(dat[0])) b = mol.GetAtomTag(int(dat[1])) c = mol.GetAtomTag(int(dat[2])) d = mol.GetAtomTag(int(dat[3])) if mol.HasDihedral(a, b, c, d): dihedral = mol.GetDihedral(a, b, c, d) else: dihedral = mol.NewDihedral(a, b, c, d) dihedral.AddType( ff.GetDihedralType(impropertype, int(dat[4]))) elif i < start_line[4] + counts[4]: # Proper dihedrals a = mol.GetAtomTag(int(dat[0])) b = mol.GetAtomTag(int(dat[1])) c = mol.GetAtomTag(int(dat[2])) d = mol.GetAtomTag(int(dat[3])) dihedral = mol.GetDihedral(a, b, c, d) if not dihedral: raise IndexError( "No dihedral found: {}-{}-{}-{}".format(*dat[:4])) dihedral.AddType( ff.GetDihedralType(propertype, int(dat[4]))) if details is not None: LoadIXDFile(details, mol) return mol
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