def minimize(selection='tmp', forcefield='MMFF94', method='steepest descent', nsteps=2000, conv=1E-6, cutoff=False, cut_vdw=6.0, cut_elec=8.0, rigid_geometry=True): """ Use openbabel to minimize the energy of a molecule. """ pdb_string = cmd.get_pdbstr(selection) name = cmd.get_legal_name(selection) obconversion = ob.OBConversion() obconversion.SetInAndOutFormats('pdb', 'pdb') mol = ob.OBMol() obconversion.ReadString(mol, pdb_string) if rigid_geometry: constraints = ob.OBFFConstraints() for angle in ob.OBMolAngleIter(mol): b, a, c = [mol.GetAtom(x + 1) for x in angle] value = mol.GetAngle(a, b, c) b, a, c = [x + 1 for x in angle] constraints.AddAngleConstraint(a, b, c, value) for i in ob.OBMolBondIter(mol): a, b = (i.GetBeginAtomIdx(), i.GetEndAtomIdx()) value = i.GetLength() constraints.AddDistanceConstraint(a, b, value) ff = ob.OBForceField.FindForceField(forcefield) ff.Setup(mol, constraints) ff.SetConstraints(constraints) else: ff = ob.OBForceField.FindForceField(forcefield) ff.Setup(mol) if cutoff: ff.EnableCutOff(True) ff.SetVDWCutOff(cut_vdw) ff.SetElectrostaticCutOff(cut_elec) if method == 'conjugate gradients': ff.ConjugateGradients(nsteps, conv) else: ff.SteepestDescent(nsteps, conv) ff.GetCoordinates(mol) nrg = ff.Energy() pdb_string = obconversion.WriteString(mol) cmd.delete(name) if name == 'all': name = 'all_' cmd.delete(selection) cmd.read_pdbstr(pdb_string, selection) return nrg
def smiles2inchi(smiles): openbabel.obErrorLog.SetOutputLevel(-1) conv = openbabel.OBConversion() conv.SetInAndOutFormats('smiles', 'inchi') conv.AddOption("F", conv.OUTOPTIONS) conv.AddOption("T", conv.OUTOPTIONS) conv.AddOption("x", conv.OUTOPTIONS, "noiso") conv.AddOption("w", conv.OUTOPTIONS) obmol = openbabel.OBMol() conv.ReadString(obmol, smiles) inchi = conv.WriteString(obmol, True) # second argument is trimWhitespace if inchi == '': return None else: return inchi
def smiles2smiles(smiles_in): openbabel.obErrorLog.SetOutputLevel(-1) conv = openbabel.OBConversion() conv.SetInAndOutFormats('smiles', 'smiles') #conv.AddOption("F", conv.OUTOPTIONS) #conv.AddOption("T", conv.OUTOPTIONS) #conv.AddOption("x", conv.OUTOPTIONS, "noiso") #conv.AddOption("w", conv.OUTOPTIONS) obmol = openbabel.OBMol() conv.ReadString(obmol, str(smiles_in)) smiles_out = conv.WriteString( obmol, True) # second argument is trimWhitespace if smiles_out == '': return None else: return smiles_out
def _ToFormat(obmol, fmt='inchi'): obConversion = openbabel.OBConversion() obConversion.AddOption("w", obConversion.OUTOPTIONS) obConversion.SetOutFormat(fmt) res = obConversion.WriteString(obmol) if not res: raise OpenBabelError("Cannot convert OBMol to %s" % fmt) if fmt == 'smiles' or fmt == 'smi': res = res.split() if res == []: raise OpenBabelError("Cannot convert OBMol to %s" % fmt) else: return res[0] elif fmt == 'inchi': return res.strip() else: return res
def smiles_to_ob(mol_string): """ Reads a SMILES string and creates a molecule object Currently, an initial guess at 3D geometry is performed by RDkit. :param mol_string: SMILES string :type mol_string: str :return: molecule object :rtype: openbabel.OBMol """ mol = initial_geom_guess(mol_string) obmol = ob.OBMol() obConv = ob.OBConversion() obConv.SetInAndOutFormats("mol", "mol") obConv.ReadString(obmol, mol) return obmol
def print_file(self, out_path, out_file='dyn.mld'): """ Print the output file with the aligned structures. """ try: os.makedirs(os.path.join(out_path, 'RESULTS')) except OSError: pass obconversion = openbabel.OBConversion() obconversion.SetOutFormat('xyz') obconversion.WriteFile(self.structures[0].mol, os.path.join(out_path, 'RESULTS', out_file)) for structure in self.structures[1:]: obconversion.Write(structure.mol)
def smiles2svg(inSmiles, withRects): """Generate a svg structure from a SMILES string.""" #print 'smiles2svg' #Deal with smiles made up of multiple distinct structures smilesList = inSmiles.split('.') svgList = [] obconv = openbabel.OBConversion() obconv.SetInAndOutFormats('smi', 'svg') for smiles in smilesList: mol = openbabel.OBMol() obconv.ReadString(mol, smiles) svg = obconv.WriteString(mol) svgList.append(svg) if len(smilesList) != len(svgList): print 'smiles2svg: len(smilesList) != len(svgList)' exit() if len(svgList) == 1: return svgList[0] elif len(svgList) == 0: return None elif len(svgList) > 1: #print 'packing' #pack, with a rectangle around the constituent components. p = organiseSVGNoRect.packer(svgList) #print 'packed' if withRects == True: outSvg = p.makeSVG('best', True) elif withRects == False: outSvg = p.makeSVG('best', False) #outSvg = p.makeSVG('best',True) else: print 'smiles2svg: ??' exit() outSvg = etree.tostring(outSvg, pretty_print=True) #outSvg = '<?xml version="1.0"?>\n'+outSvg return outSvg else: print 'smiles2svg: ???' exit()
def _crd2frag(symbols, crds, pbc=False, cell=None, return_bonds=False): atomnumber = len(symbols) if pbc: all_atoms = Atoms(symbols = symbols, positions = crds, pbc=True, cell=cell) repeated_atoms = all_atoms.repeat(2)[atomnumber:] tree = cKDTree(crds) d = tree.query(repeated_atoms.get_positions(), k=1)[0] nearest = d < 5 ghost_atoms = repeated_atoms[nearest] realnumber = np.where(nearest)[0] % atomnumber all_atoms += ghost_atoms xyzstring = ''.join((f"{atomnumber}\nDPGEN\n", "\n".join( ['{:2s} {:22.15f} {:22.15f} {:22.15f}'.format(s, x, y, z) for s, (x, y, z) in zip(symbols, crds)]))) conv = openbabel.OBConversion() conv.SetInAndOutFormats('xyz', 'mol2') mol = openbabel.OBMol() conv.ReadString(mol, xyzstring) mol2string = conv.WriteString(mol) bonds = [] linecontent = -1 for line in mol2string.split('\n'): if line.startswith("@<TRIPOS>BOND"): linecontent = 0 else: if linecontent == 0: s = line.split() if len(s) > 3: l = 12 if s[3] == 'ar' else int(s[3]) a, b = int(s[1])-1, int(s[2])-1 if a >= atomnumber and b >= atomnumber: # duplicated continue elif a >= atomnumber: a = realnumber[a-atomnumber] elif b >= atomnumber: b = realnumber[b-atomnumber] bonds.extend([[a, b, l], [b, a, l]]) bonds = np.array(bonds, ndmin=2).reshape((-1, 3)) graph = csr_matrix( (bonds[:, 2], (bonds[:, 0], bonds[:, 1])), shape=(atomnumber, atomnumber)) frag_numb, frag_index = connected_components(graph, 0) if return_bonds: return frag_numb, frag_index, graph return frag_numb, frag_index
def test_write_smiles(self): conv = ob.OBConversion() conv.SetOutFormat("smi") with TempDir() as tempdir: mol = parse_smiles("CCO") mol.SetTitle("#1") conv.WriteFile(mol, tempdir("blah.smi")) mol = parse_smiles("[NH4+]") mol.SetTitle("mol2") conv.Write(mol) conv.CloseOutFile() lines = open(tempdir("blah.smi"), "U").readlines() self.assertEquals( lines[0] == "CCO\t#1\n" or lines[0] == "OCC\t#1\n", True, repr(lines[0])) self.assertEquals(lines[1] == "[NH4+]\tmol2\n", True, repr(lines[1]))
def structure(self, value): """ Set structure Args: value (:obj:`openbabel.OBMol` or :obj:`str`): OpenBabel molecule, InChI-encoded structure, or None Raises: :obj:`ValueError`: if value is not an OpenBabel molecule, InChI-encoded structure, or None """ if value and not isinstance(value, openbabel.OBMol): ob_mol = openbabel.OBMol() conversion = openbabel.OBConversion() assert conversion.SetInFormat('inchi'), 'Unable to set format to inchi' if not conversion.ReadString(ob_mol, value): raise ValueError('`structure` must be an OpenBabel molecule, InChI-encoded structure, or None') value = ob_mol self._structure = value or None
def _compute_ecfp(system_ob, start_atom, max_degree=2): ''' Given an openbabel molecule and a starting atom (OBAtom object), compute the ECFP[max_degree]-like representation for that atom. Returns (for now) a SMILES string representing the resulting fragment. TODO(enf): Optimize this! Try InChi key and other approaches to improving this representation. ''' fragment = ob.OBMol() bonds_to_add = _bfs(system_ob, start_atom, max_degree) fragment = _construct_fragment_from_bonds(bonds_to_add) obConversion = ob.OBConversion() obConversion.SetOutFormat(str("can")) smiles = obConversion.WriteString(fragment).split("\t")[0] return (smiles)
def sdf2mdl(sdfile, mdlfilename): if os.path.exists(os.getcwd() + '/' + sdfile): converter = openbabel.OBConversion() converter.SetInAndOutFormats('sdf', 'mdl') mol = openbabel.OBMol() converter.ReadFile(mol, sdfile) print( 'if the file {} already exists, it will be overwritten...'.format( mdlfilename)) # os.system("babel %s %s.pdb"%(sdfile,sdfile[:-4])) converted = converter.WriteFile(mol, mdlfilename) if converted: print('.mdl file {} successfully written'.format(mdlfilename)) else: print('Conversion Failed! could not produce the .mdl file {} '. format(mdlfilename)) else: raise IOError('No such file or directory named ' + sdfile)
def minimization(self, options=[]): temp1 = tempfile.NamedTemporaryFile(suffix='.pdb') temp2 = tempfile.NamedTemporaryFile(suffix='.pdb') bufMol = ob.OBMol() obConversion = ob.OBConversion() obConversion.SetInAndOutFormats('pdb', 'pdb') obConversion.WriteFile(self.molecule, temp1.name) popenargs = ['obminimize'] + options + [temp1.name] subprocess.run(popenargs, stdout=temp2) obConversion.ReadFile(bufMol, temp2.name) temp1.close() temp2.close() # Update coordinates pairs = zip(ob.OBMolAtomIter(self.molecule), ob.OBMolAtomIter(bufMol)) for (ai, aj) in pairs: x, y, z = aj.x(), aj.y(), aj.z() ai.SetVector(x, y, z)
def make_coord_file(self, file_path, file_type=None, lvprt=0): """ Write the structure file. """ ftype = file_type if file_type != None else self.guess_file_type( file_path) if ftype in self.new_types: self.make_coord_new(file_path, ftype) else: obconversion = openbabel.OBConversion() if not obconversion.SetOutFormat(ftype): raise error_handler.MsgError( "Format %s not supported by openbabel for output." % ftype) if not obconversion.WriteFile(self.mol, file_path): raise error_handler.MsgError( "Error writing coordinate file %s" % file_path) if lvprt >= 1: print(("Coordinate file %s written." % file_path))
def get_InChI(attr): try: params = { "atomcoords": np.asarray(attr["atomcoords"]), "atomnos": attr["atomnos"], "charge": attr["charge"], "mult": attr["mult"] } mol = makeopenbabel(**params) obconversion = ob.OBConversion() obconversion.SetOutFormat("inchi") ob.obErrorLog.StopLogging() inchi = obconversion.WriteString(mol).strip() if inchi.startswith("InChI="): inchi = inchi.replace("InChI=", "") return inchi except: return None
def get_best_conformation(smiles=str): import openbabel mol = openbabel.OBMol() obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats("smi", "xyz") obConversion.ReadString(mol, smiles) mol.AddHydrogens() builder = openbabel.OBBuilder() builder.Build(mol) ff = openbabel.OBForceField.FindForceField("MMFF94") ff.Setup(mol) ff.SteepestDescent(250) ff.WeightedRotorSearch(200, 25) ff.ConjugateGradients(200) raw_xyz = obConversion.WriteString(mol) #print raw_xyw raw_string = str.split(raw_xyz, '\n') return raw_xyz, ff.Energy()
def getSMILES(mol, opt, partialOpt=False): if opt: min = BFGS(mol) if partialOpt: try: min.run(fmax=0.1, steps=25) except: min.run(fmax=0.1, steps=1) elif opt: try: min.run(fmax=0.1, steps=200) except: min.run(fmax=0.1, steps=1) # Get list of atomic numbers and cartesian coords from ASEmol atoms = mol.get_atomic_numbers() cart = mol.get_positions() # Create open babel molecule BABMol BABmol = openbabel.OBMol() for i in range(0, atoms.size): a = BABmol.NewAtom() a.SetAtomicNum(int(atoms[i])) a.SetVector(float(cart[i, 0]), float(cart[i, 1]), float(cart[i, 2])) # Assign bonds and fill out angles and torsions BABmol.ConnectTheDots() BABmol.FindAngles() BABmol.FindTorsions() BABmol.PerceiveBondOrders() #Create converter object to convert from XYZ to smiles obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats("xyz", "can") name = (obConversion.WriteString(BABmol)) # Convert "." to "____" to clearly differentiate between species name = name.replace('.', '____') name = name.replace('/', '') # These options make trans / cis isomers indistinguishable and ignore chirality name = name.replace('\\', '') name = name.replace('@', '') name = name.strip('\n\t') return name
def ob_mol(string, moltype): returncode, message = 0, "" try: obConversion = openbabel.OBConversion() if moltype == "smi": obConversion.SetInAndOutFormats("smi", "smi") else: obConversion.SetInAndOutFormats("sdf", "smi") mol = openbabel.OBMol() obConversion.ReadString(mol, string) except: returncode, message = -1, "-" else: # This checks if non-druglike atoms are present in the structure A = [] for a in mol.GetSpacedFormula().split(): try: int(a) except ValueError: if a not in ["+", "-"]: A.append(a) returncode = sum([ 0 if a in [ "C", "H", "N", "O", "P", "S", "B", "F", "Cl", "Br", "I", "As", "Se", "Si" ] else 1 for a in A ]) if returncode > 0: message += "+" else: message += "." mol.StripSalts() # This removes smaller fragments if present. na, mw = mol.NumHvyAtoms(), mol.GetMolWt() outSMILES = obConversion.WriteString(mol) if na > settings.LOWNA and na < settings.HIGHNA: # This checks if the number of non-H atoms is within the range message += "." else: message += "+" returncode = -2 if mw > settings.LOWMW and mw < settings.HIGHMW: # This checks if the molecular weight is within the range message += "." else: message += "+" returncode = -3 return (returncode, message, outSMILES)
def run(self): proasis_hit = ProasisHits.objects.get(crystal_name_id=self.crystal_id, refinement_id=self.refinement_id, altconf=self.altconf) proasis_out = ProasisOut.objects.get(proasis=proasis_hit, crystal=proasis_hit.crystal_name, ligand=self.ligand, ligid=self.ligid) # set openbabel to convert from sdf to mol obConv = openbabel.OBConversion() obConv.SetInAndOutFormats('sdf', 'mol') # blank mol for ob mol = openbabel.OBMol() # read pdb and write mol obConv.ReadFile(mol, self.input().path) obConv.WriteFile(mol, self.output().path) # add mol file to proasis out entry proasis_out.mol = self.output().path.split('/')[-1] proasis_out.save()
def to_canonical(smiles): """ Uses OpenBabel. Converts a SMILES string to a canonical SMILES string. smiles :: str. return :: str. """ obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats("smi", "can") outMol = openbabel.OBMol() if VERBOSE: print "Canonicalizing: %s" % str(smiles) obConversion.ReadString(outMol, str(smiles)) ans = obConversion.WriteString(outMol) if len(ans.strip()) == 0: # TODO: Something is grievously wrong return smiles raise StandardError("%s %s" % (smiles, ans.strip())) return ans.strip()
def get_chemspider_structure(csid): """ Get a molecular structure from ChemSpider, generate a PDB file of the structure, and return the name of the PDB file """ pdbpath = '{}.pdb'.format(csid) token = 'a03b1636-afc3-4204-9a2c-ede27680577c' # XXX cs = ChemSpider(token) cmpd = cs.get_compound(csid) conv = ob.OBConversion() conv.SetInAndOutFormats('mol', 'pdb') mol = ob.OBMol() conv.ReadString(mol, cmpd.mol_3d) mol.AddHydrogens() with open(pdbpath, 'w') as f: f.write(conv.WriteString(mol)) return pdbpath
def genMopFile(mol): conv = ob.OBConversion() conv.SetOutFormat("mop") if os.sep in mol.title: mop_name = mol.title[mol.title.rfind(os.sep) + 1:] + ".mop" else: mop_name = mol.title + ".mop" if not mol.OBMol.HasHydrogensAdded(): mol.addh() if not mol.OBMol.Has3D(): mol.make3D() key = "ESP MMOK VECTORS BONDS PI PRECISE ENPART AM1 GNORM=0.01 EF XYZ MULLIK +\nCharge=%d" % mol.charge conv.AddOption("k", conv.OUTOPTIONS, key) status = conv.WriteFile(mol.OBMol, mop_name) if not status: print "Error: failed to write mop file for " % mol.title return "" else: return mop_name
def _init(): # ob.OBConversion() for name in ("FP2", "FP3", "FP4", "MACCS"): ob_fingerprinter = ob.OBFingerprint.FindFingerprint(name) if ob_fingerprinter is None: _ob_get_fingerprint[name] = (None, None) else: _ob_get_fingerprint[name] = (ob_fingerprinter, ob_fingerprinter.GetFingerprint) if _ob_get_fingerprint["FP2"][0] is None: raise ImportError( "Unable to load OpenBabel FP2 fingerprinter. Check $BABEL_LIBDIR") n = _ob_get_fingerprint["FP2"][0].Getbitsperint() if n != 32: raise AssertionError( "The chemfp.ob module assumes OB fingerprints have 32 bit integers" )
def run(self): proasis_out = ProasisOut.objects.filter(proasis=ProasisHits.objects.get(crystal_name_id=self.crystal_id, refinement_id=self.refinement_id)) for o in proasis_out: lig = o.ligand infile = os.path.join(o.root, o.start, str(o.start + '_' + lig.replace(' ', '') + '.sdf')) outfile = infile.replace('sdf', 'mol') obConv = openbabel.OBConversion() obConv.SetInAndOutFormats('sdf', 'mol') mol = openbabel.OBMol() # read pdb and write mol2 obConv.ReadFile(mol, infile) obConv.WriteFile(mol, outfile) o.mol = outfile.split('/')[-1] o.save()
def read_molecules(filepath, single=False): in_format = filepath.strip().split('.')[-1] obconversion = ob.OBConversion() obconversion.SetInFormat(in_format) obmol = ob.OBMol() molecules = [] notatend = obconversion.ReadFile(obmol, filepath) while notatend: molecules.append(obmol) obmol = ob.OBMol() notatend = obconversion.Read(obmol) if single: assert (len(molecules) == 1) return molecules[0] else: return molecules
def render(smiles, hydrogens=False): """ smiles :: str. In SMILES format. hydrogens :: bool. Currently, the hydrogens option does nothing. return :: str. In SVG format. """ obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats("smi", "svg") outMol = openbabel.OBMol() if VERBOSE: print "SVGing: %s" % str(smiles) obConversion.ReadString(outMol, str(smiles)) ans = obConversion.WriteString(outMol) ## Make the svg background transparent: ## replace fill="rgb(255,255,255)" with fill-opacity="0" ans = re.sub("fill=\"white\"", "fill-opacity=\"0\"", ans) return ans
def rearrange_smiles(aa_smiles): '''Rewrite an amino-acid smiles to start with the N-term and end with the C-term.''' mol = pybel.readstring('smi', aa_smiles) n_term_pat = pybel.Smarts('[$(NCC(O)=O)]') c_term_pat = pybel.Smarts('[$(OC(=O)CN)]') #Find location of start and end atoms n_term_idx = n_term_pat.findall(mol)[0][0] c_term_idx = c_term_pat.findall(mol)[0][0] #Rewrite smiles N-term first, then C-term rearranger = openbabel.OBConversion() rearranger.SetInAndOutFormats('smi', 'smi') rearranger.AddOption('f', openbabel.OBConversion.OUTOPTIONS, str(n_term_idx)) rearranger.AddOption('l', openbabel.OBConversion.OUTOPTIONS, str(c_term_idx)) outmol = openbabel.OBMol() rearranger.ReadString(outmol, aa_smiles) return rearranger.WriteString(outmol).strip()
def exchangeAtom(C, H, molTS, molFG, outfile): # read write xyz file convTS, convFG = [ob.OBConversion() for i in range(2)] convTS.SetInAndOutFormats("xyz", "xyz") convFG.SetInAndOutFormats("xyz", "xyz") # builder builder = ob.OBBuilder() # define molecules, atoms and bond classes TS, FG = [ob.OBMol() for i in range(2)] atomH = ob.OBAtom bond = ob.OBBond() # read in xyz files convTS.ReadFile(TS, molTS) convFG.ReadFile(FG, molFG) # number of atoms in TS molecule numAtoms = TS.NumAtoms() # get hydrogen atom and its vector atomH = TS.GetAtom(H) vec = ob.vector3(float(atomH.GetX()), float(atomH.GetY()), float(atomH.GetZ())) # delete hydrogen atom TS.DeleteAtom(atomH) # put both molecules together (same coord system) TS += FG # making the bond builder.Connect(TS, C, numAtoms, vec, 1) # call opimizer opt_mmff_FG(TS, numAtoms, outfile) #convTS.WriteFile(TS, "out_xyz/" + outfile) # clear TS and FG molecule classes TS.Clear() FG.Clear()
def matchsmarts(smarts, outf, catoms): sm = openbabel.OBSmartsPattern() print('---Test for developer version----') sm.Init(smarts) print('smart is:', smarts) current_path = os.getcwd() print('current path:', current_path) print('file open:', outf) f = open(outf, 'r') s = f.read().splitlines() f.close() # moll = openbabel.OBMol() # obConversion = openbabel.OBConversion() # obConversion.SetInAndOutFormats("smi", "smi") f = open(outf, 'w') # print('in file is:', s) moll = openbabel.OBMol() # add obConversion = openbabel.OBConversion() # add obConversion.SetInAndOutFormats("smi", "smi") # add for i, mol in enumerate(s): obConversion.ReadString(moll, mol) sm.Match(moll) # sm.Match(mol) # print('mol current:', mol) smm = list(sm.GetUMapList()) print('#:', i) print('mol current:', mol) print('smm current', smm) print('catoms:', catoms) if len(smm) > 0: pmatch = smm[0] cc = '' for at in catoms: att = at - 1 # indexing cc += str(pmatch[att]) + ',' # if i < nres: f.write(mol + ' ' + cc[:-1] + '\n') # f.write(s[i]+'\n') else: pass f.close() return 0
def getOBMol(self, fst, convtype, ffclean=False): obConversion = openbabel.OBConversion() OBMol = openbabel.OBMol() if convtype == 'smistring': obConversion.SetInFormat('smi') obConversion.ReadString(OBMol, fst) else: obConversion.SetInFormat(convtype[:-1]) obConversion.ReadFile(OBMol, fst) if 'smi' in convtype: OBMol.AddHydrogens() b = openbabel.OBBuilder() b.Build(OBMol) if ffclean: forcefield = openbabel.OBForceField.FindForceField('mmff94') forcefield.Setup(OBMol) forcefield.ConjugateGradients(200) forcefield.GetCoordinates(OBMol) self.OBMol = OBMol return OBMol