openforcefield / openff-toolkit

The Open Forcefield Toolkit provides implementations of the SMIRNOFF format, parameterization engine, and other tools. Documentation available at http://open-forcefield-toolkit.readthedocs.io
http://openforcefield.org
MIT License
313 stars 92 forks source link

Strange behavior when applying `.index()` to list of molecules read from sdf #1517

Open ijpulidos opened 1 year ago

ijpulidos commented 1 year ago

Describe the bug

When I tried read a list of molecules form an sdf file and try to apply the .index method (list method) I get an unexpected behavior.

It might be a minor issue but it was unexpected.

To Reproduce The code to reproduce the issue is the following:

from openff.toolkit.topology import Molecule
molecules = Molecule.from_file("ligands.sdf")
molecules.index("some_name")

The ligands.sdf file to reproduce the issue is attached.

Output

The ipython traceback is as follows:

traceback ```python --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In [15], line 1 ----> 1 molecules.index("some_name") File ~/miniconda3/envs/openff-0.11/lib/python3.10/site-packages/openff/toolkit/topology/molecule.py:1300, in FrozenMolecule.__eq__(self, other) 1287 """ 1288 Test two molecules for equality to see if they are the chemical species, but do not check other 1289 annotated properties. (...) 1296 1297 """ 1298 # updated to use the new isomorphic checking method, with full matching 1299 # TODO the doc string did not match the previous function what matching should this method do? -> 1300 return Molecule.are_isomorphic(self, other, return_atom_map=False)[0] File ~/miniconda3/envs/openff-0.11/lib/python3.10/site-packages/openff/toolkit/topology/molecule.py:1917, in FrozenMolecule.are_isomorphic(mol1, mol2, return_atom_map, aromatic_matching, formal_charge_matching, bond_order_matching, atom_stereochemistry_matching, bond_stereochemistry_matching, strip_pyrimidal_n_atom_stereo, toolkit_registry) 1911 raise TypeError( 1912 "are_isomorphic accepts a NetworkX Graph or OpenFF " 1913 + f"(Frozen)Molecule, not {type(obj)}" 1914 ) 1916 # Quick number of atoms check. Important for large molecules -> 1917 if _object_to_n_atoms(mol1) != _object_to_n_atoms(mol2): 1918 return False, None 1920 # If the number of atoms match, check the Hill formula File ~/miniconda3/envs/openff-0.11/lib/python3.10/site-packages/openff/toolkit/topology/molecule.py:1911, in FrozenMolecule.are_isomorphic.._object_to_n_atoms(obj) 1909 return obj.number_of_nodes() 1910 else: -> 1911 raise TypeError( 1912 "are_isomorphic accepts a NetworkX Graph or OpenFF " 1913 + f"(Frozen)Molecule, not {type(obj)}" 1914 ) TypeError: are_isomorphic accepts a NetworkX Graph or OpenFF (Frozen)Molecule, not ```

I was expecting a ValueError: 'some_name' is not in list as the error output.

Computing environment (please complete the following information):

# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       2_gnu    conda-forge
amberlite                 22.0                     pypi_0    pypi
ambertools                22.0            py310h206695f_3    conda-forge
amberutils                21.0                     pypi_0    pypi
anyio                     3.6.1              pyhd8ed1ab_1    conda-forge
argon2-cffi               21.3.0             pyhd8ed1ab_0    conda-forge
argon2-cffi-bindings      21.2.0          py310h5764c6d_2    conda-forge
arpack                    3.7.0                hdefa2d7_2    conda-forge
asttokens                 2.0.8              pyhd8ed1ab_0    conda-forge
astunparse                1.6.3              pyhd8ed1ab_0    conda-forge
attrs                     22.1.0             pyh71513ae_1    conda-forge
babel                     2.10.3             pyhd8ed1ab_0    conda-forge
backcall                  0.2.0              pyh9f0ad1d_0    conda-forge
backports                 1.0                        py_2    conda-forge
backports.functools_lru_cache 1.6.4              pyhd8ed1ab_0    conda-forge
beautifulsoup4            4.11.1             pyha770c72_0    conda-forge
bleach                    5.0.1              pyhd8ed1ab_0    conda-forge
blosc                     1.21.1               h83bc5f7_3    conda-forge
boost                     1.74.0          py310h7c3ba0c_5    conda-forge
boost-cpp                 1.74.0               h75c5d50_8    conda-forge
brotli                    1.0.9                h166bdaf_7    conda-forge
brotli-bin                1.0.9                h166bdaf_7    conda-forge
brotlipy                  0.7.0           py310h5764c6d_1004    conda-forge
bzip2                     1.0.8                h7f98852_4    conda-forge
c-ares                    1.18.1               h7f98852_0    conda-forge
ca-certificates           2022.9.24            ha878542_0    conda-forge
cached-property           1.5.2                hd8ed1ab_1    conda-forge
cached_property           1.5.2              pyha770c72_1    conda-forge
cachetools                5.2.0              pyhd8ed1ab_0    conda-forge
cairo                     1.16.0            ha61ee94_1014    conda-forge
certifi                   2022.9.24          pyhd8ed1ab_0    conda-forge
cffi                      1.15.1          py310h255011f_0    conda-forge
charset-normalizer        2.1.1              pyhd8ed1ab_0    conda-forge
contourpy                 1.0.5           py310hbf28c38_0    conda-forge
cryptography              37.0.1          py310h9ce1e76_0  
cudatoolkit               11.7.0              hd8887f6_10    conda-forge
curl                      7.83.1               h2283fc2_0    conda-forge
cycler                    0.11.0             pyhd8ed1ab_0    conda-forge
cython                    0.29.32         py310hd8f1fbe_0    conda-forge
debugpy                   1.6.3           py310hd8f1fbe_0    conda-forge
decorator                 5.1.1              pyhd8ed1ab_0    conda-forge
defusedxml                0.7.1              pyhd8ed1ab_0    conda-forge
entrypoints               0.4                pyhd8ed1ab_0    conda-forge
executing                 1.1.0              pyhd8ed1ab_0    conda-forge
expat                     2.4.9                h27087fc_0    conda-forge
fftw                      3.3.10          nompi_hf0379b8_105    conda-forge
flit-core                 3.7.1              pyhd8ed1ab_0    conda-forge
font-ttf-dejavu-sans-mono 2.37                 hab24e00_0    conda-forge
font-ttf-inconsolata      3.000                h77eed37_0    conda-forge
font-ttf-source-code-pro  2.038                h77eed37_0    conda-forge
font-ttf-ubuntu           0.83                 hab24e00_0    conda-forge
fontconfig                2.14.0               hc2a2eb6_1    conda-forge
fonts-conda-ecosystem     1                             0    conda-forge
fonts-conda-forge         1                             0    conda-forge
fonttools                 4.37.3          py310h5764c6d_0    conda-forge
freetype                  2.12.1               hca18f0e_0    conda-forge
gettext                   0.19.8.1          h27087fc_1009    conda-forge
greenlet                  1.1.3           py310hd8f1fbe_0    conda-forge
hdf4                      4.2.15               h9772cbc_4    conda-forge
hdf5                      1.12.2          nompi_h4df4325_100    conda-forge
icu                       70.1                 h27087fc_0    conda-forge
idna                      3.4                pyhd8ed1ab_0    conda-forge
importlib-metadata        4.11.4          py310hff52083_0    conda-forge
importlib_metadata        4.11.4               hd8ed1ab_0    conda-forge
importlib_resources       5.9.0              pyhd8ed1ab_0    conda-forge
iniconfig                 1.1.1              pyh9f0ad1d_0    conda-forge
ipykernel                 6.15.3             pyh210e3f2_0    conda-forge
ipython                   8.5.0              pyh41d4057_1    conda-forge
ipython_genutils          0.2.0                      py_1    conda-forge
jedi                      0.18.1             pyhd8ed1ab_2    conda-forge
jinja2                    3.1.2              pyhd8ed1ab_1    conda-forge
jpeg                      9e                   h166bdaf_2    conda-forge
json5                     0.9.5              pyh9f0ad1d_0    conda-forge
jsonschema                4.16.0             pyhd8ed1ab_0    conda-forge
jupyter_client            7.3.5              pyhd8ed1ab_0    conda-forge
jupyter_core              4.11.1          py310hff52083_0    conda-forge
jupyter_server            1.18.1             pyhd8ed1ab_0    conda-forge
jupyterlab                3.4.7              pyhd8ed1ab_0    conda-forge
jupyterlab_pygments       0.2.2              pyhd8ed1ab_0    conda-forge
jupyterlab_server         2.15.1             pyhd8ed1ab_0    conda-forge
keyutils                  1.6.1                h166bdaf_0    conda-forge
kiwisolver                1.4.4           py310hbf28c38_0    conda-forge
krb5                      1.19.3               h08a2579_0    conda-forge
lcms2                     2.12                 hddcbb42_0    conda-forge
ld_impl_linux-64          2.36.1               hea4e1c9_2    conda-forge
lerc                      4.0.0                h27087fc_0    conda-forge
libblas                   3.9.0           16_linux64_openblas    conda-forge
libbrotlicommon           1.0.9                h166bdaf_7    conda-forge
libbrotlidec              1.0.9                h166bdaf_7    conda-forge
libbrotlienc              1.0.9                h166bdaf_7    conda-forge
libcblas                  3.9.0           16_linux64_openblas    conda-forge
libcurl                   7.83.1               h2283fc2_0    conda-forge
libdeflate                1.14                 h166bdaf_0    conda-forge
libedit                   3.1.20191231         he28a2e2_2    conda-forge
libev                     4.33                 h516909a_1    conda-forge
libffi                    3.4.2                h7f98852_5    conda-forge
libgcc-ng                 12.1.0              h8d9b700_16    conda-forge
libgfortran-ng            12.1.0              h69a702a_16    conda-forge
libgfortran5              12.1.0              hdcd56e2_16    conda-forge
libglib                   2.74.0               h7a41b64_0    conda-forge
libgomp                   12.1.0              h8d9b700_16    conda-forge
libiconv                  1.17                 h166bdaf_0    conda-forge
liblapack                 3.9.0           16_linux64_openblas    conda-forge
libnetcdf                 4.8.1           nompi_h21705cb_104    conda-forge
libnghttp2                1.47.0               hff17c54_1    conda-forge
libnsl                    2.0.0                h7f98852_0    conda-forge
libopenblas               0.3.21          pthreads_h78a6416_3    conda-forge
libpng                    1.6.38               h753d276_0    conda-forge
libsodium                 1.0.18               h36c2ea0_1    conda-forge
libsqlite                 3.39.3               h753d276_0    conda-forge
libssh2                   1.10.0               hf14f497_3    conda-forge
libstdcxx-ng              12.1.0              ha89aaad_16    conda-forge
libtiff                   4.4.0                h55922b4_4    conda-forge
libuuid                   2.32.1            h7f98852_1000    conda-forge
libwebp-base              1.2.4                h166bdaf_0    conda-forge
libxcb                    1.13              h7f98852_1004    conda-forge
libxml2                   2.10.2               h4c7fe37_1    conda-forge
libxslt                   1.1.35               h8affb1d_0    conda-forge
libzip                    1.9.2                hc929e4a_1    conda-forge
libzlib                   1.2.12               h166bdaf_3    conda-forge
lxml                      4.9.1           py310h5764c6d_0    conda-forge
lz4-c                     1.9.3                h9c3ff4c_1    conda-forge
lzo                       2.10              h516909a_1000    conda-forge
markupsafe                2.1.1           py310h5764c6d_1    conda-forge
matplotlib-base           3.6.0           py310h8d5ebf3_0    conda-forge
matplotlib-inline         0.1.6              pyhd8ed1ab_0    conda-forge
mdtraj                    1.9.7           py310h902c554_2    conda-forge
mistune                   2.0.4              pyhd8ed1ab_0    conda-forge
mmpbsa-py                 16.0                     pypi_0    pypi
munkres                   1.1.4              pyh9f0ad1d_0    conda-forge
nbclassic                 0.4.3              pyhd8ed1ab_0    conda-forge
nbclient                  0.6.8              pyhd8ed1ab_0    conda-forge
nbconvert                 7.0.0              pyhd8ed1ab_0    conda-forge
nbconvert-core            7.0.0              pyhd8ed1ab_0    conda-forge
nbconvert-pandoc          7.0.0              pyhd8ed1ab_0    conda-forge
nbformat                  5.6.1              pyhd8ed1ab_0    conda-forge
ncurses                   6.3                  h27087fc_1    conda-forge
nest-asyncio              1.5.5              pyhd8ed1ab_0    conda-forge
netcdf-fortran            4.6.0           nompi_hc402ea5_100    conda-forge
networkx                  2.8.6              pyhd8ed1ab_0    conda-forge
nomkl                     1.0                  h5ca1d4c_0    conda-forge
notebook                  6.4.12             pyha770c72_0    conda-forge
notebook-shim             0.1.0              pyhd8ed1ab_0    conda-forge
numexpr                   2.8.3           py310hf05e7a9_100    conda-forge
numpy                     1.23.3          py310h53a5b5f_0    conda-forge
ocl-icd                   2.3.1                h7f98852_0    conda-forge
ocl-icd-system            1.0.0                         1    conda-forge
openeye-toolkits          2022.1.1                py310_0    openeye
openff-amber-ff-ports     0.0.3              pyh6c4a22f_0    conda-forge
openff-forcefields        2.0.0              pyh6c4a22f_0    conda-forge
openff-interchange        0.2.1              pyhd8ed1ab_0    conda-forge
openff-interchange-base   0.2.1              pyhd8ed1ab_0    conda-forge
openff-toolkit            0.11.1             pyhd8ed1ab_0    conda-forge
openff-toolkit-base       0.11.1             pyhd8ed1ab_0    conda-forge
openff-units              0.1.8              pyh1a96a4e_0    conda-forge
openff-utilities          0.1.6              pyh1a96a4e_0    conda-forge
openjpeg                  2.5.0                h7d73246_1    conda-forge
openmm                    7.7.0           py310hccf1d78_1    conda-forge
openssl                   3.0.5                h166bdaf_2    conda-forge
packaging                 21.3               pyhd8ed1ab_0    conda-forge
packmol                   20.010               h86c2bf4_0    conda-forge
packmol-memgen            1.2.3rc0                 pypi_0    pypi
pandas                    1.5.0           py310h769672d_0    conda-forge
pandoc                    2.19.2               ha770c72_0    conda-forge
pandocfilters             1.5.0              pyhd8ed1ab_0    conda-forge
panedr                    0.5.2                      py_0    conda-forge
parmed                    3.4.3           py310hd8f1fbe_2    conda-forge
parso                     0.8.3              pyhd8ed1ab_0    conda-forge
pbr                       5.10.0             pyhd8ed1ab_0    conda-forge
pcre2                     10.37                hc3806b6_1    conda-forge
pdb4amber                 22.0                     pypi_0    pypi
perl                      5.32.1          2_h7f98852_perl5    conda-forge
pexpect                   4.8.0              pyh9f0ad1d_2    conda-forge
pickleshare               0.7.5                   py_1003    conda-forge
pillow                    9.2.0           py310hbd86126_2    conda-forge
pint                      0.19.2             pyhd8ed1ab_0    conda-forge
pip                       22.2.2             pyhd8ed1ab_0    conda-forge
pixman                    0.40.0               h36c2ea0_0    conda-forge
pkgutil-resolve-name      1.3.10             pyhd8ed1ab_0    conda-forge
pluggy                    1.0.0           py310hff52083_3    conda-forge
prometheus_client         0.14.1             pyhd8ed1ab_0    conda-forge
prompt-toolkit            3.0.31             pyha770c72_0    conda-forge
psutil                    5.9.2           py310h5764c6d_0    conda-forge
pthread-stubs             0.4               h36c2ea0_1001    conda-forge
ptyprocess                0.7.0              pyhd3deb0d_0    conda-forge
pure_eval                 0.2.2              pyhd8ed1ab_0    conda-forge
py                        1.11.0             pyh6c4a22f_0    conda-forge
pycairo                   1.21.0          py310h96fc21a_1    conda-forge
pycparser                 2.21               pyhd8ed1ab_0    conda-forge
pydantic                  1.10.2          py310h5764c6d_0    conda-forge
pygments                  2.13.0             pyhd8ed1ab_0    conda-forge
pyopenssl                 22.0.0             pyhd8ed1ab_1    conda-forge
pyparsing                 3.0.9              pyhd8ed1ab_0    conda-forge
pyrsistent                0.18.1          py310h5764c6d_1    conda-forge
pysocks                   1.7.1              pyha2e5f31_6    conda-forge
pytables                  3.7.0           py310hb60b9b2_2    conda-forge
pytest                    7.1.3           py310hff52083_0    conda-forge
python                    3.10.6          ha86cf86_0_cpython    conda-forge
python-constraint         1.4.0                      py_0    conda-forge
python-dateutil           2.8.2              pyhd8ed1ab_0    conda-forge
python-fastjsonschema     2.16.2             pyhd8ed1ab_0    conda-forge
python_abi                3.10                    2_cp310    conda-forge
pytraj                    2.0.6                    pypi_0    pypi
pytz                      2022.2.1           pyhd8ed1ab_0    conda-forge
pyzmq                     24.0.1          py310h330234f_0    conda-forge
rdkit                     2022.03.5       py310h1c297d8_0    conda-forge
readline                  8.1.2                h0f457ee_0    conda-forge
reportlab                 3.5.68          py310h94fcab3_1    conda-forge
requests                  2.28.1             pyhd8ed1ab_1    conda-forge
sander                    22.0                     pypi_0    pypi
scipy                     1.9.1           py310hdfbd76f_0    conda-forge
send2trash                1.8.0              pyhd8ed1ab_0    conda-forge
setuptools                65.4.0             pyhd8ed1ab_0    conda-forge
six                       1.16.0             pyh6c4a22f_0    conda-forge
smirnoff99frosst          1.1.0              pyh44b312d_0    conda-forge
snappy                    1.1.9                hbd366e4_1    conda-forge
sniffio                   1.3.0              pyhd8ed1ab_0    conda-forge
soupsieve                 2.3.2.post1        pyhd8ed1ab_0    conda-forge
sqlalchemy                1.4.41          py310h5764c6d_0    conda-forge
stack_data                0.5.1              pyhd8ed1ab_0    conda-forge
terminado                 0.15.0          py310hff52083_0    conda-forge
tinycss2                  1.1.1              pyhd8ed1ab_0    conda-forge
tk                        8.6.12               h27826a3_0    conda-forge
tomli                     2.0.1              pyhd8ed1ab_0    conda-forge
tornado                   6.2             py310h5764c6d_0    conda-forge
traitlets                 5.4.0              pyhd8ed1ab_0    conda-forge
typing-extensions         4.3.0                hd8ed1ab_0    conda-forge
typing_extensions         4.3.0              pyha770c72_0    conda-forge
tzdata                    2022d                h191b570_0    conda-forge
unicodedata2              14.0.0          py310h5764c6d_1    conda-forge
urllib3                   1.26.11            pyhd8ed1ab_0    conda-forge
wcwidth                   0.2.5              pyh9f0ad1d_2    conda-forge
webencodings              0.5.1                      py_1    conda-forge
websocket-client          1.4.1              pyhd8ed1ab_0    conda-forge
wheel                     0.37.1             pyhd8ed1ab_0    conda-forge
xmltodict                 0.13.0             pyhd8ed1ab_0    conda-forge
xorg-kbproto              1.0.7             h7f98852_1002    conda-forge
xorg-libice               1.0.10               h7f98852_0    conda-forge
xorg-libsm                1.2.3             hd9c2040_1000    conda-forge
xorg-libx11               1.7.2                h7f98852_0    conda-forge
xorg-libxau               1.0.9                h7f98852_0    conda-forge
xorg-libxdmcp             1.1.3                h7f98852_0    conda-forge
xorg-libxext              1.3.4                h7f98852_1    conda-forge
xorg-libxrender           0.9.10            h7f98852_1003    conda-forge
xorg-libxt                1.2.1                h7f98852_2    conda-forge
xorg-renderproto          0.11.1            h7f98852_1002    conda-forge
xorg-xextproto            7.3.0             h7f98852_1002    conda-forge
xorg-xproto               7.0.31            h7f98852_1007    conda-forge
xz                        5.2.6                h166bdaf_0    conda-forge
zeromq                    4.3.4                h9c3ff4c_1    conda-forge
zipp                      3.8.1              pyhd8ed1ab_0    conda-forge
zlib                      1.2.12               h166bdaf_3    conda-forge
zstd                      1.5.2                h6239696_4    conda-forge

ligands.sdf.zip

mattwthompson commented 1 year ago

Woah, that's weird and I can reproduce this. Molecule.from_file returns a List[Molecule] when given a multi-molecule SDF file. It looks like list.index is choking on equality checking, which makes sense given that we override it.

There's probably a way to make some sort of class MoleculeList(list) that overrides

The docs suggest that list.index is supposed to raise a ValueError when the item is not found in the list (which would be the case here - "some_item" is not going to be found in a list of Molecule objects). Switching that exception would be a marginal API break. Raising a new exception that inherits from both would be either not a behavior change or a marginal one, depending on one's perspective of things. TypeError does seem like the right one to use here according to the official docs, if using built-in exception types.