Re: [Rdkit-discuss] Inchi which flavour??
Open-Source Cheminformatics and Machine Learning
Brought to you by:
glandrum
From: Paolo T. <pao...@gm...> - 2019-10-09 22:33:41
|
Hi Mike, please find here a solution which I have just tested and works well on both Unix and Windows. You need to redirect the C++ stderr stream with ctypes around the call whose output you wish to grab. This can be done defining a context manager that uses ctypes: import os import sys import datetime import ctypes import io import tempfile from contextlib import contextmanager # Adapted from # https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/ if (sys.platform == "win32"): kernel32 = ctypes.WinDLL("kernel32") # https://docs.microsoft.com/en-us/windows/console/getstdhandle C_STD_ERROR_HANDLE = -12 c_stderr = kernel32.GetStdHandle(C_STD_ERROR_HANDLE) c_flush = kernel32.FlushFileBuffers else: libc = ctypes.CDLL(None) c_stderr = ctypes.c_void_p.in_dll(libc, "stderr") c_flush = libc.fflush @contextmanager def stderr_redirector(stream): # The original fd stderr points to. original_stderr_fd = sys.stderr.fileno() def _redirect_stderr(to_fd): """Redirect stderr to the given file descriptor.""" # Flush the C-level buffer stderr c_flush(c_stderr) # Flush and close sys.stderr - also closes the file descriptor (fd) sys.stderr.close() # Make original_stderr_fd point to the same file as to_fd os.dup2(to_fd, original_stderr_fd) # Create a new sys.stderr that points to the redirected fd sys.stderr = io.TextIOWrapper(os.fdopen(original_stderr_fd, 'wb')) # Save a copy of the original stderr fd in saved_stderr_fd saved_stderr_fd = os.dup(original_stderr_fd) try: # Create a temporary file and redirect stderr to it tfile = tempfile.TemporaryFile(mode='w+b') _redirect_stderr(tfile.fileno()) # Yield to caller, then redirect stderr back to the saved fd yield _redirect_stderr(saved_stderr_fd) # Copy contents of temporary file to the given stream tfile.flush() tfile.seek(0, io.SEEK_SET) stream.write(tfile.read()) finally: tfile.close() os.close(saved_stderr_fd) Then, all you need to grab the RDKit warning printed to stderr is use the stderr_redirector() context manager around the relevant call, then check the grabbed output for relevant content. For instance, in your example wrap the Chem.MolToInchi() call as follows: f = io.BytesIO() with stderr_redirector(f): InChi = Chem.MolToInchi(Chem.MolFromSmiles(y)) grabbed_stderr = f.getvalue().decode('utf-8') if ("WARNING" in grabbed_stderr): print("caught: ", grabbed_stderr) Cheers, p. On 09/10/2019 18:10, Mike Mazanetz wrote: > > Hi, > > Many thanks this, it is very helpful to see some code. > > Yes, as it stands, I am yet to get warnings which are seen in stdout > being sent to a file, only errors seem to find their way to my files. > > Usually Warnings about stereochemistry don’t get captured. Anyone see > this, I’m guessing it’s the same for failed InChI’s too? > > Thanks, > > mike > > *From:*Scalfani, Vincent <vfs...@ua...> > *Sent:* 09 October 2019 14:40 > *To:* Maciek Wójcikowski <ma...@wo...>; Greg Landrum > <gre...@gm...> > *Cc:* RDKit Discuss <rdk...@li...> > *Subject:* Re: [Rdkit-discuss] Inchi which flavour?? > > Hi Macjek and Mike, > > If I understand your question correctly, you can specify InChI option > parameters when calculating InChIs. Here is an example: > > m = Chem.MolFromSmiles('CCC1=CN=C(NC1=O)NC') > > Chem.MolToInchi(m) > > 'InChI=1S/C7H11N3O/c1-3-5-4-9-7(8-2)10-6(5)11/h4H,3H2,1-2H3,(H2,8,9,10,11)' > > Now, try with one of the non-standard options such as FixedH: > > Chem.MolToInchi(m,'/FixedH') > > 'InChI=1/C7H11N3O/c1-3-5-4-9-7(8-2)10-6(5)11/h4H,3H2,1-2H3,(H2,8,9,10,11)/f/h8,10H' > > To answer the question of what happens when the InChI calculation > fails, I get an empty string. > > m = > Chem.MolFromSmiles('[C@H]1([C@H](C1C2[C@@H]([C@@H]2C(=O)O)C(=O)O)C(=O)O)C(=O)O') > > Chem.MolToInchi(m) > > ' ' > > There is also an InChI option that can warn on empty structures, and > calculate an empty InChI, which I am assuming is supposed to be > ‘InChI=1S//’, however, when trying this option I get the same result > as above. > > Chem.MolToInchi(m,'/WarnOnEmptyStructure') > > ' ' > > I hope that helps. > > Vin > > *From:*Maciek Wójcikowski <ma...@wo... > <mailto:ma...@wo...>> > *Sent:* Wednesday, October 9, 2019 3:41 AM > *To:* Greg Landrum <gre...@gm... > <mailto:gre...@gm...>> > *Cc:* RDKit Discuss <rdk...@li... > <mailto:rdk...@li...>> > *Subject:* Re: [Rdkit-discuss] Inchi which flavour?? > > Mike, > > On top of what Greg said what might be particularly useful is an > options parameter where you can pass some non default params to InChI > call. > > śr., 9 paź 2019, 07:22 użytkownik Greg Landrum <gre...@gm... > <mailto:gre...@gm...>> napisał: > > Hi Mike, > > The InChI API itself is not exposed. The contents of the > module are in the documentation along with some explanations of > how to call it: > > http://rdkit.org/docs/source/rdkit.Chem.rdinchi.html > > If something is missing there, please let us know. > > -greg > > On Tue, Oct 8, 2019 at 5:20 PM <mi...@no... > <mailto:mi...@no...>> wrote: > > Dear RdKit users, > > I was reading the inchi module docs and I couldn't find > methods to call the InChI API. Are these exposed in RDKit? > > It says the default is the standard Inchi. What happens when > this conversion fails? > > Thanks, > > Mike > > _______________________________________________ > Rdkit-discuss mailing list > Rdk...@li... > <mailto:Rdk...@li...> > https://lists.sourceforge.net/lists/listinfo/rdkit-discuss > > _______________________________________________ > Rdkit-discuss mailing list > Rdk...@li... > <mailto:Rdk...@li...> > https://lists.sourceforge.net/lists/listinfo/rdkit-discuss > > > > _______________________________________________ > Rdkit-discuss mailing list > Rdk...@li... > https://lists.sourceforge.net/lists/listinfo/rdkit-discuss |