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 <vfscalf...@ua.edu>
*Sent:* 09 October 2019 14:40
*To:* Maciek Wójcikowski <mac...@wojcikowski.pl>; Greg Landrum
<greg.land...@gmail.com>
*Cc:* RDKit Discuss <rdkit-discuss@lists.sourceforge.net>
*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 <mac...@wojcikowski.pl
<mailto:mac...@wojcikowski.pl>>
*Sent:* Wednesday, October 9, 2019 3:41 AM
*To:* Greg Landrum <greg.land...@gmail.com
<mailto:greg.land...@gmail.com>>
*Cc:* RDKit Discuss <rdkit-discuss@lists.sourceforge.net
<mailto:rdkit-discuss@lists.sourceforge.net>>
*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 <greg.land...@gmail.com
<mailto:greg.land...@gmail.com>> 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...@novadatasolutions.co.uk
<mailto:mi...@novadatasolutions.co.uk>> 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
Rdkit-discuss@lists.sourceforge.net
<mailto:Rdkit-discuss@lists.sourceforge.net>
https://lists.sourceforge.net/lists/listinfo/rdkit-discuss
_______________________________________________
Rdkit-discuss mailing list
Rdkit-discuss@lists.sourceforge.net
<mailto:Rdkit-discuss@lists.sourceforge.net>
https://lists.sourceforge.net/lists/listinfo/rdkit-discuss
_______________________________________________
Rdkit-discuss mailing list
Rdkit-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rdkit-discuss
_______________________________________________
Rdkit-discuss mailing list
Rdkit-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rdkit-discuss