def read_sdf_to_fb_mol(filename): """ read sdf file and return ForceBalance.molecule.Molecule object """ from forcebalance.molecule import Molecule, Elements import numpy as np mol_list = read_split_mols(filename) assert len(mol_list) == 1, 'file contains multiple molecules' oe_mol = mol_list[0] # create a new molecule fb_mol = Molecule() # load elems fb_mol.elem = [Elements[a.GetAtomicNum()] for a in oe_mol.GetAtoms()] noa = len(fb_mol.elem) # load coordinates coords_dict = oe_mol.GetCoords() fb_mol.xyzs = [np.array([coords_dict[i] for i in range(noa)])] # load bonds bonds, bond_orders = [], [] for oe_bond in oe_mol.GetBonds(): idx_a = oe_bond.GetBgnIdx() idx_b = oe_bond.GetEndIdx() bond = (idx_a, idx_b) if idx_a <= idx_b else (idx_b, idx_a) bonds.append(bond) bond_orders.append(oe_bond.GetOrder()) fb_mol.bonds = bonds fb_mol.bond_orders = bond_orders # load atomic formal charges atomic_formal_charges = [a.GetFormalCharge() for a in oe_mol.GetAtoms()] molecular_charge = sum(atomic_formal_charges) fb_mol.Data['molecular_charge'] = molecular_charge fb_mol.Data['atomic_formal_charges'] = atomic_formal_charges # set the oe_mol as one attribute fb_mol.oe_mol = oe_mol # set the cmiles id mapped_smiles = cmiles.utils.mol_to_smiles(oe_mol) fb_mol.Data['cmiles_id'] = cmiles.generator.get_molecule_ids(mapped_smiles) return fb_mol
def GenerateBox(pdbin, pdbout, box, nmol, tries): """ Call genbox. (Confirmed working with Gromacs version 4.6.7 and 5.1.4). Mainly checks whether genbox ran correctly. Parameters ---------- pdbin : str Name of input PDB file containing a single molecule. pdbout : str Name of output PDB file containing solvent box. box : float Solvent box size, should be determined previously. nmol : int Number of molecules to go into the solvent box tries : int Parameter for genbox to try inserting each molecule (tries) times Returns ------- None If successful, produces "pdbout" containing solvent box. """ if which('gmx'): gmxcmd = 'gmx insert-molecules' elif which('genbox'): gmxcmd = 'genbox' else: raise RuntimeError( 'gmx and/or genbox not in PATH. Please source Gromacs environment variables.' ) fout = open('genbox.out', 'w') ferr = open('genbox.err', 'w') subprocess.Popen( '%s -ci %s -o genbox.pdb -box %.3f %.3f %.3f -nmol %i -try %i' % (gmxcmd, pdbin, box, box, box, nmol, tries), shell=True, stdout=fout, stderr=ferr) fout.close() ferr.close() t0 = time.time() print("Running %s to create a solvent box..." % gmxcmd) print("Time elapsed: % .3f seconds" % (time.time() - t0)) nmol_out = 0 for line in open('genbox.err').readlines(): if 'Output configuration contains' in line: nmol_out = int(line.split()[-2]) if nmol_out == 0: raise RuntimeError('genbox failed to produce an output configuration') elif nmol_out != nmol: raise RuntimeError( 'genbox failed to create a box with %i molecules (actual %i); ' 'please retry with increased box size or number of tries' % (nmol, nmol_out)) else: # genbox throws away the CONECT records in the PDB, this operation adds them back. M1 = Molecule(pdbin, build_topology=False) M = Molecule('genbox.pdb', build_topology=False) solventbox_bonds = [] # Loop over the number of molecules in the solvent box for i in range(nmol): for j in M1.bonds: # Add the bonds for molecule number "i" in the solvent box solventbox_bonds.append((j[0] + i * M1.na, j[1] + i * M1.na)) M.bonds = solventbox_bonds M.write(pdbout) print( "-=# Output #=- Created %s containing solvent box with %i molecules and length %.3f" % (pdbout, nmol, box))