diff --git a/.vscode/settings.json b/.vscode/settings.json index 9e875f7..0969248 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,5 @@ { - "python.defaultInterpreterPath": "${workspaceFolder}/.pixi/envs/dev/bin/python" + "python.defaultInterpreterPath": "${workspaceFolder}/.pixi/envs/dev/bin/python", + "python-envs.defaultEnvManager": "renan-r-santos.pixi-code:pixi", + "python-envs.defaultPackageManager": "renan-r-santos.pixi-code:pixi" } diff --git a/CHANGELOG.md b/CHANGELOG.md index eec72a2..264bea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### Added +- `geom.transform.transition()` for determining the transition-state geometry between two geometries via `StereoCondensedReactionGraph`. ## [0.0.19] - 2026-07-17 ### Added diff --git a/pixi.lock b/pixi.lock index cbe74ca..e69133f 100644 --- a/pixi.lock +++ b/pixi.lock @@ -20,8 +20,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.1.0-py313hf46b229_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py313hc8edb43_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hac629b4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.21-py313h5d5ffb9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-abi-5.0.1.80-hf414acd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_0.conda @@ -66,6 +68,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.4-hd5a49e9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libraqm-0.10.5-h75b3fb1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/librdkit-2026.03.4-h72e46c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_18.conda @@ -90,12 +93,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/pycairo-1.29.0-py313h3f29d12_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.3-py313h843e2db_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.14-h6add32d_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rdkit-2026.03.4-py313hc9b5091_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.0-py313h4b8bb8b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.51-py313h54dd161_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.7-py313h07c4f96_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py313h07c4f96_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda @@ -104,12 +109,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.13.14-py313hd8ed1ab_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda @@ -123,11 +132,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fonttools-4.63.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/freetype-py-2.3.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.15.0-pyh53cf698_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda @@ -137,10 +150,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py3dmol-2.5.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.3-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.13.14-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/reportlab-4.5.1-pyhc364b38_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rlpycairo-0.4.0-pyh6c17108_0.conda @@ -152,9 +167,22 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda - - conda_source: automol[d00f6c44] @ . + - conda_source: automol[5fa33e89] @ . + - pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/21/0e/8459ca4413e1a21a06c97d134bfaf18adfd27cea068813dc0faae06cbf00/cssselect2-0.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/1b/291dd75b5ed494eb484801f39e6572192d322e6cd3d68fab8a6dde743c48/graphrc-1.3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/0d/f494a2ec62ab56ffd44da4f236db374421fe0cd1e39d9ebc9785751eb432/periodictable-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4b/78/b7814d82f29baf7e629b9fcf945ca6ff31c516235d7286197ab81b44465a/stereomolgraph-0.0.22b0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/53/bb/d653059b3d72813a849160964c2c3400b5f12fb9d17c799f64f94e885a9c/irmsd-0.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/60/45/c7b5c3168458db837e8ceab06dc77824e18202679d0463f0e8f002143a97/tinycss2-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/f9/bf414dc8e352eba65699ffe42406dc8d55adcb3ba757e02463e6d2cfca5b/xyzgraph-1.6.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6f/f6/5d5da46d47c8e65c2a393b236af339bd1a863ef4974ec86e9691b750ab4a/resvg_py-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/87/45/8edbde2bf05b02b43c18e557455447d885b0074aeca637a6276fd0838b14/xyzrender-0.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/e0/5011747466414c12cac8a8df77aa235068669a6a5a5df301a96209db6054/cairosvg-2.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/76/96b7ffc917962e6f74bff1ec850838796f58bedceac6f610834898af6462/cclib-1.8.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl dev: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -427,7 +455,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - - conda_source: automol[d00f6c44] @ . + - conda_source: automol[5fa33e89] @ . - pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/21/0e/8459ca4413e1a21a06c97d134bfaf18adfd27cea068813dc0faae06cbf00/cssselect2-0.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/23/06/b4f06ca7afb5d9e942c642980c308ffcfa1fa0e8b0a3ddbec78483ef1614/keepachangelog-2.0.0-py3-none-any.whl @@ -486,7 +514,7 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause AND MIT AND EPL-2.0 purls: - - pkg:pypi/backports-zstd?source=compressed-mapping + - pkg:pypi/backports-zstd?source=hash-mapping run_exports: {} size: 242845 timestamp: 1781450812380 @@ -653,7 +681,7 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/debugpy?source=compressed-mapping + - pkg:pypi/debugpy?source=hash-mapping run_exports: {} size: 2825625 timestamp: 1780390153372 @@ -902,6 +930,7 @@ packages: constrains: - binutils_impl_linux-64 2.46.1 license: GPL-3.0-only + license_family: GPL run_exports: {} size: 745303 timestamp: 1784214507189 @@ -1119,20 +1148,19 @@ packages: purls: [] size: 1041788 timestamp: 1771378212382 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 - md5: 57736f29cc2b0ec0b6c2952d3f101b6a +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_20.conda + sha256: e3b7bb287d1685b15781a6d9e3408d6ddaff23f5a1d0d6c0140619dd3950fe72 + md5: 3533de187cf7283f96bfdb28ad73e2bc depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 constrains: - - libgcc-ng ==15.2.0=*_19 - - libgomp 15.2.0 he0feb66_19 + - libgomp 15.2.0 he0feb66_20 + - libgcc-ng ==15.2.0=*_20 license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL run_exports: {} - size: 1041084 - timestamp: 1778269013026 + size: 1041122 + timestamp: 1784923795784 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 md5: d5e96b1ed75ca01906b3d2469b4ce493 @@ -1194,18 +1222,17 @@ packages: purls: [] size: 603262 timestamp: 1771378117851 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda - sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b - md5: faac990cb7aedc7f3a2224f2c9b0c26c +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_20.conda + sha256: 30b8ff1bf43871a17c9de99e56171ef54cfbe690ffa86681628db5a00af97cf7 + md5: 49321086c41bb58fc4b6cd8cbb74679d depends: - __glibc >=2.17,<3.0.a0 license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL run_exports: strong: - _openmp_mutex >=4.5 - size: 603817 - timestamp: 1778268942614 + size: 603998 + timestamp: 1784923730278 - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f md5: 915f5995e94f60e9a4826e0b0920ee88 @@ -1396,19 +1423,18 @@ packages: purls: [] size: 5852330 timestamp: 1771378262446 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc - md5: 5794b3bdc38177caf969dabd3af08549 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_20.conda + sha256: b5eadda8fb0df262f0d424c4a0c8c1c8d65d904ce622f07936c793ea1b8a39d9 + md5: fbd3d5506b11b5cfc916b29263b6b6f7 depends: - __glibc >=2.17,<3.0.a0 - - libgcc 15.2.0 he0feb66_19 + - libgcc 15.2.0 he0feb66_20 constrains: - - libstdcxx-ng ==15.2.0=*_19 + - libstdcxx-ng ==15.2.0=*_20 license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL run_exports: {} - size: 5852044 - timestamp: 1778269036376 + size: 5857690 + timestamp: 1784923825011 - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_18.conda sha256: 3c902ffd673cb3c6ddde624cdb80f870b6c835f8bf28384b0016e7d444dd0145 md5: 6235adb93d064ecdf3d44faee6f468de @@ -1708,7 +1734,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/pandas?source=compressed-mapping + - pkg:pypi/pandas?source=hash-mapping run_exports: {} size: 15001668 timestamp: 1778602610159 @@ -1866,10 +1892,10 @@ packages: size: 37398694 timestamp: 1781258934574 python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.6-habeac84_100_cp314.conda - build_number: 100 - sha256: 6d28ac2b061179deb434d3d57afa98ffd20ec3c5d44ab8048a1ca33424b22d38 - md5: 0b9b2f83b5b600e1ac38becde8d0dd44 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.6-habeac84_101_cp314.conda + build_number: 101 + sha256: ee8f2006e1724b1f2e9e0ccc5a7cfdcab973460faa2f63ac1f6e44fdad4c0344 + md5: 78975a41cf3c525da654f17e35bfca9e depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 @@ -1879,8 +1905,8 @@ packages: - libgcc >=14 - liblzma >=5.8.3,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.53.2,<4.0a0 - - libuuid >=2.42.1,<3.0a0 + - libsqlite >=3.53.3,<4.0a0 + - libuuid >=2.42.2,<3.0a0 - libzlib >=1.3.2,<2.0a0 - ncurses >=6.6,<7.0a0 - openssl >=3.5.7,<4.0a0 @@ -1895,8 +1921,8 @@ packages: - python_abi 3.14.* *_cp314 noarch: - python - size: 36717183 - timestamp: 1781255094700 + size: 36869055 + timestamp: 1784910110714 python_site_packages_path: lib/python3.14/site-packages - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py313h3dea7bd_1.conda sha256: ef7df29b38ef04ec67a8888a4aa039973eaa377e8c4b59a7be0a1c50cd7e4ac6 @@ -2079,6 +2105,22 @@ packages: - tk >=8.6.13,<8.7.0a0 size: 3301196 timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd70dff1_3.conda + build_number: 103 + sha256: 43624eab22f5f29df7d6ffe914cf442f28fd559b55b290906255492826e636e8 + md5: 48a1049e710857572fc2a832aa394d9f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.2,<2.0a0 + constrains: + - xorg-libx11 >=1.8.13,<2.0a0 + license: TCL + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3550916 + timestamp: 1784229071544 - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.7-py313h07c4f96_0.conda sha256: ed2f17b2bc92389187b47e7444aa7d6ab6c70c3f3ba6bf2ced508027e60e82cb md5: 9665531f18d2bcbc946e3ba0cf53ea91 @@ -2090,7 +2132,7 @@ packages: license: Apache-2.0 license_family: Apache purls: - - pkg:pypi/tornado?source=compressed-mapping + - pkg:pypi/tornado?source=hash-mapping run_exports: {} size: 885824 timestamp: 1781006802459 @@ -2128,19 +2170,19 @@ packages: run_exports: {} size: 408932 timestamp: 1770909099052 -- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.29-h2112641_0.conda - sha256: a5b92c2cedcaba3b877d6c4aab42853f57b6bb26f9c901cfb5aa5da03269d310 - md5: 5552b8d0f33cf86753d35da1b3ec0736 +- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.31-h2112641_0.conda + sha256: 972605a00975e31e550b761b77c38c4700f98541de277998d4d5e6c4372de4f8 + md5: 06a0144a3d10bf336d9f16472d3e2fcc depends: + - __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 - - __glibc >=2.17,<3.0.a0 constrains: - __glibc >=2.17 license: Apache-2.0 OR MIT run_exports: {} - size: 20782187 - timestamp: 1784166603021 + size: 20873084 + timestamp: 1784709345198 - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.8-h29f5ae7_1.conda sha256: 01e4bd3ef63e893ef908b57cbde1132c49141f6794eb2d54558627876e02d9d0 md5: ccec3ef299ab5d8892ebec5485bc9616 @@ -2154,20 +2196,20 @@ packages: purls: [] size: 19114693 timestamp: 1777486136750 -- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-build-0.11.29-h9a1d3cd_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/uv-build-0.11.31-h9a1d3cd_0.conda noarch: python - sha256: 1cef7c8411dc878a2fa68a7c7139819aaac7f95775bf693453a337a76af3a4de - md5: b467f466bf61b9e722b4b0aed9dc1f17 + sha256: 68968271d12dd4744f07dd4a7d4345c0739b9741a7960f86bcc97f5c0001ddbb + md5: 00755d769e50e96591a6b06d866463d6 depends: - python >=3.10 - - libgcc >=14 - __glibc >=2.17,<3.0.a0 + - libgcc >=14 constrains: - __glibc >=2.17 license: Apache-2.0 AND MIT AND BSD-2-Clause run_exports: {} - size: 2040501 - timestamp: 1784165418663 + size: 2042045 + timestamp: 1784703682715 - conda: https://conda.anaconda.org/conda-forge/linux-64/uvloop-0.22.1-py313h07c4f96_1.conda sha256: 77a220ecf6c1467f94d6adda5fb1296f558f3f3044842dc0a52881eab5908dc0 md5: 266caaa8701a13482ea924a77897b1e4 @@ -2516,15 +2558,15 @@ packages: purls: [] size: 131039 timestamp: 1776865545798 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda - sha256: f8e3c730fa14ee3f170493779f06522c4acf89169f43db4f039727709b6419cf - md5: a9965dd99f683c5f444428f896635716 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + sha256: 0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6 + md5: 0f51e2391ade309db462a55611263e9c depends: - __unix license: ISC run_exports: {} - size: 128866 - timestamp: 1781708962055 + size: 131780 + timestamp: 1784754889428 - conda: https://conda.anaconda.org/conda-forge/noarch/cachetools-7.0.6-pyhd8ed1ab_0.conda sha256: f31f02b8bfa312bca79abbc24a0dd1930291cbdaca321b6d1c230687b175a9ff md5: 14e77b3ebe7b8e37f6254a59ee245184 @@ -2857,6 +2899,7 @@ packages: license_family: BSD purls: - pkg:pypi/flexcache?source=hash-mapping + run_exports: {} size: 16674 timestamp: 1733663669958 - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -2870,6 +2913,7 @@ packages: license_family: BSD purls: - pkg:pypi/flexparser?source=hash-mapping + run_exports: {} size: 28686 timestamp: 1733663636245 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 @@ -3437,6 +3481,7 @@ packages: license_family: BSD purls: - pkg:pypi/pint?source=hash-mapping + run_exports: {} size: 245230 timestamp: 1773969991837 - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda @@ -3508,6 +3553,7 @@ packages: license_family: MIT purls: - pkg:pypi/py3dmol?source=hash-mapping + run_exports: {} size: 13737 timestamp: 1769417304572 - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -4226,6 +4272,13 @@ packages: run_exports: {} size: 119135 timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + sha256: b928c30ddcb0e3f544c6eade8352737e6e610e263276b90232db6a578ef899d8 + md5: fcb489df604d100968b737f2cb6076c6 + license: LicenseRef-Public-Domain + run_exports: {} + size: 118849 + timestamp: 1784250406640 - conda: https://conda.anaconda.org/conda-forge/noarch/unidecode-1.4.0-pyhcf101f3_1.conda sha256: 184d1377f88251983ef5154aea0d6cb73108afc8510ed66526afb1c44b2e1259 md5: 53cb4b14ab0841e104e2bd11ee64b840 @@ -4327,7 +4380,7 @@ packages: - pkg:pypi/zipp?source=hash-mapping size: 24461 timestamp: 1776131454755 -- conda_source: automol[d00f6c44] @ . +- conda_source: automol[5fa33e89] @ . variants: target_platform: noarch depends: @@ -4346,25 +4399,25 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_20.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_20.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_20.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.6-habeac84_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.6-habeac84_101_cp314.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.29-h2112641_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-build-0.11.29-h9a1d3cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd70dff1_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.11.31-h2112641_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-build-0.11.31-h9a1d3cd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda - pypi: https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl name: defusedxml version: 0.7.1 diff --git a/pixi.toml b/pixi.toml index 417e93c..f9a7d28 100644 --- a/pixi.toml +++ b/pixi.toml @@ -36,7 +36,6 @@ ipykernel = "*" [feature.dev.pypi-dependencies] keepachangelog = "*" -xyzrender = ">=0.3.1, <0.4" [feature.docs.dependencies] sphinx = "*" @@ -51,6 +50,7 @@ dev = { features = ["dev", "docs"], solve-group = "default"} [pypi-dependencies] stereomolgraph = ">=0.0.22b0" irmsd = "==0.1.1" +xyzrender = ">=0.3.1, <0.4" [feature.dev.tasks] # Manage pyproject.toml with uv diff --git a/src/automol/geom/__init__.py b/src/automol/geom/__init__.py index 2ffec2c..42f379c 100644 --- a/src/automol/geom/__init__.py +++ b/src/automol/geom/__init__.py @@ -5,6 +5,7 @@ from .core import ( Geometry, from_rdkit_mol, + from_stereo_mol_graph, from_xyz_block, from_xyz_file, hill_formula, @@ -23,6 +24,7 @@ ) from .internal import angles, bonds, dihedrals, set_distance from .properties import adjacency_matrix, center_of_mass, distance_keys, distance_matrix +from .transform import transition from .vibration import ( harmonic_zpv, mass_weight_vector, @@ -45,6 +47,7 @@ "distance_matrix", "eckart_frame", "from_rdkit_mol", + "from_stereo_mol_graph", "from_xyz_block", "from_xyz_file", "harmonic_zpv", @@ -62,6 +65,7 @@ "set_distance", "stereo_mol_graph", "transform", + "transition", "translational_normal_modes", "vibrational_analysis", "view", diff --git a/src/automol/geom/core.py b/src/automol/geom/core.py index 32807f1..2086652 100644 --- a/src/automol/geom/core.py +++ b/src/automol/geom/core.py @@ -217,6 +217,12 @@ def stereo_mol_graph(geo: Geometry) -> StereoMolGraph: return StereoMolGraph.from_geometry(sm_geo) # ty:ignore[invalid-argument-type] +def from_stereo_mol_graph(smg: StereoMolGraph, *, charge: int = 0) -> Geometry: + """Instantiate a Geometry from a StereoMolGraph.""" + mol = smg.to_rdmol(charge=charge) + return from_rdkit_mol(mol) + + def hill_formula(geo: Geometry) -> str: """Render the molecular formula in Hill order.""" counts = Counter(s.capitalize() for s in geo.symbols) diff --git a/src/automol/geom/transform.py b/src/automol/geom/transform.py index 49bf68d..65b1335 100644 --- a/src/automol/geom/transform.py +++ b/src/automol/geom/transform.py @@ -6,6 +6,9 @@ import numpy as np from numpy.typing import ArrayLike from scipy.spatial.transform import Rotation +from stereomolgraph import StereoCondensedReactionGraph + +from .core import from_stereo_mol_graph, stereo_mol_graph if TYPE_CHECKING: from .core import Geometry @@ -93,3 +96,39 @@ def rotate( mask = slice(None) if keys is None else list(keys) geo.coordinates[mask] = rot.apply(geo.coordinates[mask]) return geo + + +def transition(geo1: "Geometry", geo2: "Geometry") -> "Geometry": + """Determine the transition geometry between two geometries. + + Parameters + ---------- + geo1 + Initial geometry. + geo2 + Final geometry. + + Returns + ------- + Geometry. + """ + if geo1.spin != geo2.spin: + msg = f"Geometries must have the same spin: {geo1.spin} != {geo2.spin}" + raise ValueError(msg) + + smg1 = stereo_mol_graph(geo1) + smg2 = stereo_mol_graph(geo2) + scrg = StereoCondensedReactionGraph.from_graphs(smg1, smg2) + + active_h = [a for a in scrg.active_atoms() if scrg.get_atom_type(a) == 1] + for h in active_h: + scrg.set_atom_attribute(h, "atom_type", 8) + + ts_smg = scrg.ts() + ts_geo = from_stereo_mol_graph(ts_smg) + ts_geo.spin = geo1.spin + + for h in active_h: + ts_geo.symbols[h] = "H" + + return ts_geo diff --git a/tests/test_transform.py b/tests/test_transform.py index 95babad..9e02198 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -1,6 +1,7 @@ """Geometry transform tests.""" import numpy as np +import pytest from scipy.spatial.transform import Rotation from automol import Geometry, geom @@ -58,3 +59,45 @@ def test__rotate_in_place(water: Geometry) -> None: result = geom.transform.rotate(water, rot, in_place=True) assert result is water assert np.allclose(water.coordinates, expected) + + +def test__transition_raises_for_mismatched_spin(water: Geometry) -> None: + """Test that transition() rejects geometries with different spins.""" + water_triplet = water.model_copy(update={"spin": 2}) + assert water.spin != water_triplet.spin + with pytest.raises(ValueError, match="spin"): + geom.transform.transition(water, water_triplet) + + +def test__transition_identity(water: Geometry) -> None: + """Test the (degenerate) transition between a geometry and itself.""" + ts_geo = geom.transform.transition(water, water) + assert ts_geo.symbols == water.symbols + assert ts_geo.spin == water.spin + assert ts_geo.coordinates.shape == water.coordinates.shape + assert np.all(np.isfinite(ts_geo.coordinates)) + + +def test__transition_hydrogen_abstraction() -> None: + """Test the transition geometry for an H-abstraction reaction. + + F-H + Cl -> F + H-Cl: the migrating H atom breaks its bond to F and forms + a new bond to Cl. + """ + reactant = Geometry( + symbols=["F", "H", "Cl"], + coordinates=[[0, 0, 0], [0.92, 0, 0], [3.5, 0, 0]], + charge=0, + spin=0, + ) + product = Geometry( + symbols=["F", "H", "Cl"], + coordinates=[[0, 0, 0], [3.0, 0, 0], [4.27, 0, 0]], + charge=0, + spin=0, + ) + ts_geo = geom.transform.transition(reactant, product) + assert ts_geo.symbols == reactant.symbols + assert ts_geo.spin == reactant.spin + assert ts_geo.coordinates.shape == reactant.coordinates.shape + assert np.all(np.isfinite(ts_geo.coordinates))