Describe the bug
After loading in molecules from the MiniDrugBank.sdf, I noticed that using either the RDKit or OpenEye toolkit wrappers resulted in subtly different Molecule representations in a select few files. It seems that OpenEye is adding one or more protons at some point while reading from the file. This results in a different number of Molecule.n_atoms as shown below. Manually counting the atoms shows that OpenEye includes one extra proton than in the original sdf file or the RDKit molecule.
To Reproduce
DrugBank_178.zip
Loading DrugBank_178.sdf using Molecule.from_file with both toolkits and counting the atoms:
import openforcefield
from openforcefield.utils import get_data_file_path
from openforcefield.utils.toolkits import RDKitToolkitWrapper, OpenEyeToolkitWrapper
from openforcefield.topology.molecule import Molecule
# path to DrugBank_178.sdf file
drug_bank_file = get_data_file_path('molecules/DrugBank_178.sdf')
rdkit_toolkit_wrapper = RDKitToolkitWrapper()
open_eye_toolkit_wrapper = OpenEyeToolkitWrapper()
# Load in the molecules using separate toolkits
OFF_using_rd = Molecule.from_file(drug_bank_file,
toolkit_registry=rdkit_toolkit_wrapper,
file_format='sdf',
allow_undefined_stereo=True)
OFF_using_oe = Molecule.from_file(drug_bank_file,
toolkit_registry=open_eye_toolkit_wrapper,
file_format='sdf',
allow_undefined_stereo=True)
assert(OFF_using_rd.n_atoms == OFF_using_oe.n_atoms)
# 45 atoms 46 atoms
Output
Traceback (most recent call last):
File "/home/coda3831/anaconda3/envs/openff-dev/openforcefield/openforcefield/Connor/Issue_Adding_Protons.py", line 24, in <module>
assert(OFF_using_rd.n_atoms == OFF_using_oe.n_atoms)
AssertionError
Computing environment (please complete the following information):
conda list # Name Version Build Channel
_libgcc_mutex 0.1 conda_forge conda-forge
_openmp_mutex 4.5 1_gnu conda-forge
amberlite 16.0 pypi_0 pypi
ambertools 20.9 pypi_0 pypi
argon2-cffi 20.1.0 py37h8f50634_2 conda-forge
arpack 3.7.0 hc6cf775_2 conda-forge
astroid 2.4.2 py37_0
async_generator 1.10 py_0 conda-forge
attrs 20.2.0 pyh9f0ad1d_0 conda-forge
backports 1.0 py_2 conda-forge
backports.functools_lru_cache 1.6.1 py_0 conda-forge
bleach 3.2.1 pyh9f0ad1d_0 conda-forge
boost 1.74.0 py37h48f8a5e_1 conda-forge
boost-cpp 1.74.0 h9359b55_0 conda-forge
brotlipy 0.7.0 py37hb5d75c8_1001 conda-forge
bson 0.5.9 py_0 conda-forge
bzip2 1.0.8 h516909a_3 conda-forge
c-ares 1.16.1 h516909a_3 conda-forge
ca-certificates 2020.10.14 0
cairo 1.16.0 h488836b_1006 conda-forge
certifi 2020.6.20 pyhd3eb1b0_3
cffi 1.14.3 py37h00ebd2e_1 conda-forge
chardet 3.0.4 py37he5f6b98_1008 conda-forge
cryptography 3.2.1 py37hc72a4ac_0 conda-forge
curl 7.71.1 he644dc0_8 conda-forge
cycler 0.10.0 py_2 conda-forge
cython 0.29.21 py37hb892b2f_1 conda-forge
decorator 4.4.2 py_0 conda-forge
defusedxml 0.6.0 py_0 conda-forge
entrypoints 0.3 py37hc8dfbb8_1002 conda-forge
fftw 3.3.8 nompi_h7f3a6c3_1112 conda-forge
fftw3f 3.3.4 2 omnia
fontconfig 2.13.1 h1056068_1002 conda-forge
freetype 2.10.4 h7ca028e_0 conda-forge
gettext 0.19.8.1 hf34092f_1004 conda-forge
hdf4 4.2.13 hf30be14_1003 conda-forge
hdf5 1.10.6 nompi_h54c07f9_1110 conda-forge
icu 67.1 he1b5a44_0 conda-forge
idna 2.10 pyh9f0ad1d_0 conda-forge
importlib-metadata 2.0.0 py_1 conda-forge
importlib_metadata 2.0.0 1 conda-forge
iniconfig 1.1.1 pyh9f0ad1d_0 conda-forge
ipykernel 5.3.4 py37hc6149b9_1 conda-forge
ipython 5.8.0 py37_1 conda-forge
ipython_genutils 0.2.0 py_1 conda-forge
ipywidgets 7.5.1 pyh9f0ad1d_1 conda-forge
isort 5.6.4 py_0
jinja2 2.11.2 pyh9f0ad1d_0 conda-forge
jpeg 9d h36c2ea0_0 conda-forge
jsonschema 3.2.0 py_2 conda-forge
jupyter_client 6.1.7 py_0 conda-forge
jupyter_core 4.6.3 py37hc8dfbb8_2 conda-forge
jupyterlab_pygments 0.1.2 pyh9f0ad1d_0 conda-forge
kiwisolver 1.3.0 py37hc928c03_0 conda-forge
krb5 1.17.1 hfafb76e_3 conda-forge
lazy-object-proxy 1.4.3 py37h7b6447c_0
lcms2 2.11 hbd6801e_0 conda-forge
ld_impl_linux-64 2.35 h769bd43_9 conda-forge
libblas 3.9.0 2_openblas conda-forge
libcblas 3.9.0 2_openblas conda-forge
libcurl 7.71.1 hcdd3856_8 conda-forge
libedit 3.1.20191231 he28a2e2_2 conda-forge
libev 4.33 h516909a_1 conda-forge
libffi 3.2.1 he1b5a44_1007 conda-forge
libgcc-ng 9.3.0 h5dbcf3e_17 conda-forge
libgfortran-ng 7.5.0 hae1eefd_17 conda-forge
libgfortran4 7.5.0 hae1eefd_17 conda-forge
libglib 2.66.2 hbe7bbb4_0 conda-forge
libgomp 9.3.0 h5dbcf3e_17 conda-forge
libiconv 1.16 h516909a_0 conda-forge
liblapack 3.9.0 2_openblas conda-forge
libnetcdf 4.7.4 nompi_hefab0ff_106 conda-forge
libnghttp2 1.41.0 h8cfc5f6_2 conda-forge
libopenblas 0.3.12 pthreads_hb3c22a3_1 conda-forge
libpng 1.6.37 h21135ba_2 conda-forge
libsodium 1.0.18 h516909a_1 conda-forge
libssh2 1.9.0 hab1572f_5 conda-forge
libstdcxx-ng 9.3.0 h2ae2ef3_17 conda-forge
libtiff 4.1.0 hc7e4089_6 conda-forge
libuuid 2.32.1 h14c3975_1000 conda-forge
libwebp-base 1.1.0 h516909a_3 conda-forge
libxcb 1.13 h14c3975_1002 conda-forge
libxml2 2.9.10 h68273f3_2 conda-forge
lz4-c 1.9.2 he1b5a44_3 conda-forge
markupsafe 1.1.1 py37hb5d75c8_2 conda-forge
matplotlib-base 3.3.2 py37hc9afd2a_1 conda-forge
mccabe 0.6.1 py37_1
mistune 0.8.4 py37h8f50634_1002 conda-forge
mmpbsa-py 16.0 pypi_0 pypi
more-itertools 8.6.0 pyhd8ed1ab_0 conda-forge
msgpack-python 1.0.0 py37h99015e2_2 conda-forge
nbclient 0.5.1 py_0 conda-forge
nbconvert 6.0.7 py37hc8dfbb8_2 conda-forge
nbformat 5.0.8 py_0 conda-forge
ncurses 6.2 he1b5a44_2 conda-forge
nest-asyncio 1.4.1 py_0 conda-forge
netcdf-fortran 4.5.3 nompi_hfef6a68_101 conda-forge
networkx 2.5 py_0 conda-forge
nglview 2.7.7 pyh5ca1d4c_1 conda-forge
notebook 6.1.4 py37hc8dfbb8_1 conda-forge
numpy 1.19.2 py37h7008fea_1 conda-forge
olefile 0.46 pyh9f0ad1d_1 conda-forge
openeye-toolkits 2020.1.0 py37_0 openeye
openforcefield 0.8.0+48.g78b7a33f dev_0 <develop>
openforcefields 1.3.0 py_0 omnia
openmm 7.4.2 py37_cuda101_rc_1 omnia
openssl 1.1.1h h7b6447c_0
packaging 20.4 pyh9f0ad1d_0 conda-forge
packmol-memgen 1.1.0rc0 pypi_0 pypi
pandas 1.1.4 py37h10a2094_0 conda-forge
pandoc 2.11.0.4 hd18ef5c_0 conda-forge
pandocfilters 1.4.2 py_1 conda-forge
parmed at20RC5+54.g5702a232fe.dirty pypi_0 pypi
pcre 8.44 he1b5a44_0 conda-forge
pdb4amber 1.7.dev0 pypi_0 pypi
perl 5.30.3 h516909a_1 conda-forge
pexpect 4.8.0 pyh9f0ad1d_2 conda-forge
pickleshare 0.7.5 py_1003 conda-forge
pillow 8.0.1 py37h718be6c_0 conda-forge
pip 20.2.4 py_0 conda-forge
pixman 0.38.0 h516909a_1003 conda-forge
pluggy 0.13.1 py37he5f6b98_3 conda-forge
prometheus_client 0.8.0 pyh9f0ad1d_0 conda-forge
prompt_toolkit 1.0.15 py_1 conda-forge
pthread-stubs 0.4 h14c3975_1001 conda-forge
ptyprocess 0.6.0 py_1001 conda-forge
py 1.9.0 pyh9f0ad1d_0 conda-forge
pycairo 1.20.0 py37h01af8b0_1 conda-forge
pycparser 2.20 pyh9f0ad1d_2 conda-forge
pygments 2.7.2 py_0 conda-forge
pylint 2.6.0 py37_0
pyopenssl 19.1.0 py_1 conda-forge
pyparsing 2.4.7 pyh9f0ad1d_0 conda-forge
pyrsistent 0.17.3 py37h8f50634_1 conda-forge
pysocks 1.7.1 py37he5f6b98_2 conda-forge
pytest 6.1.2 py37h89c1867_0 conda-forge
python 3.7.8 h6f2ec95_1_cpython conda-forge
python-dateutil 2.8.1 py_0 conda-forge
python_abi 3.7 1_cp37m conda-forge
pytraj 2.0.5 pypi_0 pypi
pytz 2020.1 pyh9f0ad1d_0 conda-forge
pyyaml 5.3.1 py37hb5d75c8_1 conda-forge
pyzmq 19.0.2 py37hac76be4_2 conda-forge
rdkit 2020.09.1 py37h0c252aa_0 conda-forge
readline 8.0 he28a2e2_2 conda-forge
requests 2.24.0 pyh9f0ad1d_0 conda-forge
sander 16.0 pypi_0 pypi
scipy 1.5.2 py37h8911b10_2 conda-forge
send2trash 1.5.0 py_0 conda-forge
setuptools 49.6.0 py37he5f6b98_2 conda-forge
simplegeneric 0.8.1 py_1 conda-forge
six 1.15.0 pyh9f0ad1d_0 conda-forge
smirnoff99frosst 1.1.0 py37_1 omnia
sqlite 3.33.0 h4cf870e_1 conda-forge
terminado 0.9.1 py37hc8dfbb8_1 conda-forge
testpath 0.4.4 py_0 conda-forge
tk 8.6.10 hed695b0_1 conda-forge
toml 0.10.1 pyh9f0ad1d_0 conda-forge
tornado 6.1 py37h4abf009_0 conda-forge
traitlets 5.0.5 py_0 conda-forge
typed-ast 1.4.1 py37h7b6447c_0
urllib3 1.25.11 py_0 conda-forge
wcwidth 0.2.5 pyh9f0ad1d_2 conda-forge
webencodings 0.5.1 py_1 conda-forge
wheel 0.35.1 pyh9f0ad1d_0 conda-forge
widgetsnbextension 3.5.1 py37hc8dfbb8_4 conda-forge
wrapt 1.11.2 py37h7b6447c_0
xmltodict 0.12.0 py_0 conda-forge
xorg-kbproto 1.0.7 h14c3975_1002 conda-forge
xorg-libice 1.0.10 h516909a_0 conda-forge
xorg-libsm 1.2.3 h84519dc_1000 conda-forge
xorg-libx11 1.6.12 h516909a_0 conda-forge
xorg-libxau 1.0.9 h14c3975_0 conda-forge
xorg-libxdmcp 1.1.3 h516909a_0 conda-forge
xorg-libxext 1.3.4 h516909a_0 conda-forge
xorg-libxrender 0.9.10 h516909a_1002 conda-forge
xorg-libxt 1.2.0 h516909a_0 conda-forge
xorg-renderproto 0.11.1 h14c3975_1002 conda-forge
xorg-xextproto 7.3.0 h14c3975_1002 conda-forge
xorg-xproto 7.0.31 h14c3975_1007 conda-forge
xz 5.2.5 h516909a_1 conda-forge
yaml 0.2.5 h516909a_0 conda-forge
zeromq 4.3.3 he1b5a44_2 conda-forge
zipp 3.4.0 py_0 conda-forge
zlib 1.2.11 h516909a_1010 conda-forge
zstd 1.4.5 h6597ccf_2 conda-forge
Additional context
The Following molecules from /openff-dev/openforcefield/openforcefield/data/molecules/MiniDrugBank.sdf have the same problem. The common thread appears to be sulfate and phosphate groups:
problem_mols = ['DrugBank_178',
'DrugBank_246',
'DrugBank_700',
'DrugBank_1564',
'DrugBank_1634',
'DrugBank_1700',
'DrugBank_1962',
'DrugBank_2052',
'DrugBank_2082',
'DrugBank_2148',
'DrugBank_2210',
'DrugBank_2519',
'DrugBank_2642',
'DrugBank_3930',
'DrugBank_4662',
'DrugBank_5043',
'DrugBank_5418',
'DrugBank_5847']
Thanks for the concise report, @connordavel. I've seen all sorts of problems with phosphates and sulfates before, and I wonder how many of them can be attributed to this.
CC #762 -- I think this behavior in OpenEyeToolkitWrapper might be a bug that we WANT to avoid, instead of adding it to RDKitToolkitWrapper as well.
Just to weigh in on this - I think this is a bug but a bug in the RDKit toolkit wrapper. DrugBank_178 has an implicit hydrogen on the hydroxyl oxygen which is part of the sulfuric acid monoester group.
While the OpenEye wrapper correctly converts this to an explicit hydrogen before conversion to an OpenFF molecule, the RDKit wrapper does not and hence this is incorrectly missing on the final OpenFF molecule.
# path to DrugBank_178.sdf file
drug_bank_file = 'DrugBank_178.sdf'
rd_molecule = next(iter(Chem.SupplierFromFilename(
drug_bank_file, removeHs=False, sanitize=False, strictParsing=True
)))
oe_stream = oechem.oemolistream(drug_bank_file)
oe_molecule = next(iter(oe_stream.GetOEMols()))
n_oe_implicit = sum(atom.GetImplicitHCount() for atom in oe_molecule.GetAtoms())
>>> 1
n_rd_implicit = sum(atom.GetNumImplicitHs() for atom in rd_molecule.GetAtoms())
>>> 1
oe_index = [atom.GetIdx() for atom in oe_molecule.GetAtoms() if atom.GetImplicitHCount() > 0][0]
>>> 18
rd_index = [atom.GetIdx() for atom in rd_molecule.GetAtoms() if atom.GetNumImplicitHs() > 0][0]
>>> 18
So arguably RDKit not converting implicit hydrogens to explicit hydrogens is a critical bug, and #762 a critical bug fix.
Does the above behavior hold true for other molecules in that list?
Here's the results of reading and writing the attached file using OpenEyeToolkitWrapper and RDKitToolkitWrapper:
Initial:

OpenEyeToolkitWrapper roundtripped:

RDKitToolkitWrapper roundtripped:

Is there something in the SDF's non-3D information to indicate that there should really be an hydrogen on the sulfate?
Per the Accelerys/Biovia/Dassault CTFile spec (pp 40-41), the columns of the ATOM block should be
xxxxx.xxxxyyyyy.yyyyzzzzz.zzzzaaaddcccssshhhbbbvvvHHHrrriiimmmnnneee
where hhh is "number of implicit Hs". In DrugBank178's ATOM block [1], all hhh values are 0. Confusingly, all ccc values are ALSO zero, even though we'd expect the O with the single bond to have either a negative charge or a proton.
So I think it's ambiguous. I've subconsciously developed a few "rule of thumbs" for cases like this, and the one that applies best here is "Since the molecule has at least SOME explicit hydrogens, the user must be referencing this EXACT protonation state, and I shouldn't consider any hyrdrogens to be implicit".
[1] DrugBank_178.sdf, truncated before BONDS block
45 48 0 0 1 0 0 0 0 0999 V2000
#(Adding the column string above for reference, though I'm not sure if I've aligned columns correctly re:whitespace on the left)
xxxxx.xxxxyyyyy.yyyyzzzzz.zzzzaaaddcccssshhhbbbvvvHHHrrriiimmmnnneee
-1.9269 -0.1803 0.9467 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.7191 0.4635 0.6693 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.3722 2.2905 2.0886 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.8751 0.3890 1.8150 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.5958 1.6575 2.3697 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.4392 1.6966 1.2436 C 0 0 0 0 0 0 0 0 0 0 0 0
-7.5416 -2.2886 4.0062 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.5467 2.3541 3.3125 C 0 0 0 0 0 0 0 0 0 0 0 0
-8.2489 -1.1053 4.6454 C 0 0 0 0 0 0 0 0 0 0 0 0
-4.9507 1.7565 3.3354 C 0 0 0 0 0 0 0 0 0 0 0 0
-7.1491 -0.0344 4.7031 C 0 0 0 0 0 0 0 0 0 0 0 0
-4.1795 -1.8473 2.0454 C 0 0 0 0 0 0 0 0 0 0 0 0
-5.5269 -2.5101 2.3932 C 0 0 0 0 0 0 0 0 0 0 0 0
-4.2135 -0.2943 2.0809 C 0 0 1 0 0 0 0 0 0 0 0 0
-4.8640 0.2310 3.3984 C 0 0 2 0 0 0 0 0 0 0 0 0
-6.2294 -0.4358 3.5558 C 0 0 1 0 0 0 0 0 0 0 0 0
-6.0903 -1.9657 3.7013 C 0 0 1 0 0 0 0 0 0 0 0 0
-5.2692 -2.4593 4.9069 C 0 0 0 0 0 0 0 0 0 0 0 0
2.0515 1.0684 2.6166 O 0 0 0 0 0 0 0 0 0 0 0 0
-8.0749 -3.3695 3.7938 O 0 0 0 0 0 0 0 0 0 0 0 0
3.1159 2.8635 1.3350 O 0 0 0 0 0 0 0 0 0 0 0 0
2.4831 0.7537 0.2267 O 0 0 0 0 0 0 0 0 0 0 0 0
0.7382 2.3235 0.9776 O 0 0 0 0 0 0 0 0 0 0 0 0
2.2270 1.7023 1.3100 S 0 0 0 0 0 0 0 0 0 0 0 0
-2.1104 -1.1342 0.4614 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.0036 -0.0053 -0.0011 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.1490 3.2578 2.5343 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.1192 2.2986 4.3219 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.6229 3.4152 3.0458 H 0 0 0 0 0 0 0 0 0 0 0 0
-9.0702 -0.7916 3.9947 H 0 0 0 0 0 0 0 0 0 0 0 0
-8.6160 -1.3589 5.6420 H 0 0 0 0 0 0 0 0 0 0 0 0
-5.4914 2.1600 4.1985 H 0 0 0 0 0 0 0 0 0 0 0 0
-5.5033 2.0655 2.4388 H 0 0 0 0 0 0 0 0 0 0 0 0
-7.5713 0.9670 4.5742 H 0 0 0 0 0 0 0 0 0 0 0 0
-6.6283 -0.0551 5.6664 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.4019 -2.2133 2.7274 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.8979 -2.1967 1.0453 H 0 0 0 0 0 0 0 0 0 0 0 0
-6.2365 -2.3328 1.5742 H 0 0 0 0 0 0 0 0 0 0 0 0
-5.3989 -3.5981 2.4477 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.8602 0.0164 1.2454 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.2272 -0.0285 4.2541 H 0 0 0 0 0 0 0 0 0 0 0 0
-6.7976 -0.2184 2.6346 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.2195 -2.2489 4.7335 H 0 0 0 0 0 0 0 0 0 0 0 0
-5.4143 -3.5277 5.0236 H 0 0 0 0 0 0 0 0 0 0 0 0
-5.6035 -1.9441 5.8008 H 0 0 0 0 0 0 0 0 0 0 0 0
[2] I read though a [nextmove article](https://nextmovesoftware.com/blog/2013/02/27/explicit-and-implicit-hydrogens-taking-liberties-with-valence/ on this, but I'm not sure if it applies here or provides a clear answer
Would it be possible to track this molecule back to another source, which may provide more information about whether or not this hydrogen should be there? openff/toolkit/data/molecules/MiniDrugBank_ff.mol2 has no charges on this molecule, but I don't really trust that.
I'm inclined to side with OpenEye on this one - mostly because of the lack of a formal charge on the hydrogen, which seems like a marginally more glaring omission than a hydrogen, and somewhat because there's already a place in which we're missing hydrogens in the RDKit wrapper. There could also be some explanation about different functional groups are treated differently, i.e. the sulfate/phosphate groups implied to have enough implicit hydrogens to maintain charge neutrality, but hydrogens explicitly tagged to the heavy atoms in other functional groups. But, of course, not much confidence with all this ambiguity ...
To clarify something in my post above, the two pictures I show above are using the OpenEyeToolkitWrapper and RDKitToolkitWrapper, instead of just oechem and rdkit.Chem directly. So that's showing the results of _our usage_ of those toolkits (ie. to/from_file using the different backends), not OE and RDKit's default behavior (This doesn't contradict anything Matt just posted, I just wanted to clarify)
Does the above behavior hold true for other molecules in that list?
@mattwthompson Yes, I believe so. Many of the molecules in the list have similar groups (such as sulfates, phosphates) with ambiguous info on implicit hydrogens. In general, problem molecules include sulfurs and phosphorous (not only sulfates and phosphates). For a non-sulfate example, take the following graph of DrugBank_2642. The top graph includes all atoms from the OpenEye toolkit molecule, whereas the bottom uses the RDkit toolkit.

This molecule has a similarly ambiguous sdf block:
DrugBank_2642
OpenBabel01151909533D
5 4 0 0 0 0 0 0 0 0999 V2000
1.8389 1.9802 -1.0140 S 0 0 0 0 0 0 0 0 0 0 0 0
-1.4335 -2.4496 0.5285 S 0 0 0 0 0 0 0 0 0 0 0 0
-0.0139 1.1143 -1.1960 S 0 0 0 0 0 0 0 0 0 0 0 0
0.0838 -1.1962 1.1123 S 0 0 0 0 0 0 0 0 0 0 0 0
-0.6038 0.6980 0.7247 S 0 0 0 0 0 0 0 0 0 0 0 0
1 3 1 0 0 0 0
2 4 1 0 0 0 0
3 5 1 0 0 0 0
4 5 1 0 0 0 0
M END
$$$$
All molecules in the list follow a similar trend.
That molecule provides a nice test case; there are no explicit hydrogens to cause the ambiguity of the molecule above (a mix of explicit hydrogens and some hydrogens that could be implicit, depending on the interpretation). But that molecule is still somewhat ambiguous in terms of what it should have; I don't know if a pentavalent linear sulfur is chemically sensible or not, i.e. if that molecule really should have hydrogens or not.
Most helpful comment
@mattwthompson Yes, I believe so. Many of the molecules in the list have similar groups (such as sulfates, phosphates) with ambiguous info on implicit hydrogens. In general, problem molecules include sulfurs and phosphorous (not only sulfates and phosphates). For a non-sulfate example, take the following graph of DrugBank_2642. The top graph includes all atoms from the OpenEye toolkit molecule, whereas the bottom uses the RDkit toolkit.
DrugBank_2642.zip
This molecule has a similarly ambiguous sdf block:
All molecules in the list follow a similar trend.