diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..887a2c18 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# SCM syntax highlighting & preventing 3-way merges +pixi.lock merge=binary linguist-language=YAML linguist-generated=true diff --git a/docs/api/lr_reduction.rst b/docs/api/lr_reduction.rst index 68e3fd7f..77c36dca 100644 --- a/docs/api/lr_reduction.rst +++ b/docs/api/lr_reduction.rst @@ -87,10 +87,10 @@ lr_reduction.time_resolved :undoc-members: :show-inheritance: -lr_reduction.typing +lr_reduction.types ------------------- -.. automodule:: lr_reduction.typing +.. automodule:: lr_reduction.types :members: :undoc-members: :show-inheritance: diff --git a/pixi.lock b/pixi.lock index 413bb5d5..91db16a4 100644 --- a/pixi.lock +++ b/pixi.lock @@ -8,6 +8,8 @@ environments: - url: https://prefix.dev/pixi-build-backends/ indexes: - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 @@ -20,13 +22,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.12.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py311h49ec1c0_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asteval-1.0.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.2-h39aace5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_5.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports.tarfile-1.2.0-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py311h6b1f9c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda @@ -44,6 +54,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/codecov-2.1.13-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-25.11.1-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda @@ -52,10 +63,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py311hdf67eae_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.13.1-py311h3778330_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.11.14-py311hd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.3-py311h2005dd1_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hd9c7081_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.18-py311hc665b79_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda @@ -65,6 +79,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/editables-0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/euphonic-1.4.5-py311h0372a8f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -77,6 +92,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.61.1-py311h3778330_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/freeglut-3.2.2-ha6d2627_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/freeimage-3.18.0-h49ef1fa_24.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda @@ -84,6 +100,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/future-1.0.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.86.3-h5192d8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.86.3-hf516916_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gmpy2-2.2.1-py311h92a432a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gst-plugins-base-1.24.11-h651a532_0.conda @@ -110,26 +128,46 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.9.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/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.context-6.0.2-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.functools-4.4.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jasper-4.2.8-he3c4edf_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/jeepney-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jemalloc-5.2.0-he1b5a44_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jsoncpp-1.9.6-hf42df4d_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.25.1-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.25.1-he01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-1.1.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.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_console-6.6.3-pyhd8ed1ab_1.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/jupyter_events-0.12.0-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/keyring-25.7.0-pyha804496_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.9-py311h724c32c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lame-3.100-h166bdaf_1003.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.17-h717163a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda @@ -189,6 +227,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libraw-0.21.4-h9969a89_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/librdkafka-2.11.1-hdd48ec7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsndfile-1.2.2-hc7d488a_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda @@ -215,21 +254,31 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py311h3778330_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.9.4-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.9.4-py311h2b939e6_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/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.8.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mpc-1.3.1-h24ddda3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mpfr-4.2.1-h90cbb55_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.32.9-hc50e24c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/muparser-2.3.4-h27087fc_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-4.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.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/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.1.3-py311h71ddf71_0.conda @@ -240,7 +289,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-he970967_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/orsopy-1.2.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda @@ -256,9 +308,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/poco-1.14.2-h0a6e815_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prettytable-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.1-py311haee01d2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pulseaudio-client-17.0-h9a6aba3_3.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/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycifrw-5.0.1-py311h49ec1c0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py311h49ec1c0_3.conda @@ -279,9 +336,12 @@ environments: - 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-dotenv-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py311h3778330_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py311h2315fbb_0.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/qt-main-5.15.15-h3c3fd16_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.10.1-h6f76662_3.conda @@ -296,6 +356,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-toolbelt-1.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-py-4.1.0-pyhd8ed1ab_0.conda @@ -306,6 +369,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.3-py311hbe70eeb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.4.1-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/seekpath-2.1.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda @@ -314,6 +378,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/spglib-2.7.0-py311hd78beb3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx_rtd_theme-3.0.2-pyha770c72_0.conda @@ -324,8 +389,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sympy-1.14.0-pyh2585a3b_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2022.3.0-h8d10470_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda @@ -343,11 +412,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.0.1-py311hdf67eae_6.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uncertainties-3.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.0-py311h49ec1c0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unixodbc-2.3.14-h69e2008_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/userpath-1.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.9.21-h76e24b7_0.conda @@ -355,7 +426,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.35.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.24.0-hd6090a7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.14-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-image-0.4.0-hb711507_2.conda @@ -382,6 +457,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.6-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda @@ -399,6 +475,8 @@ environments: - url: https://prefix.dev/pixi-build-backends/ indexes: - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 @@ -409,12 +487,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.12.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-3.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py311h49ec1c0_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/asteval-1.0.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.2-h39aace5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-25.4.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_5.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports.tarfile-1.2.0-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py311h6b1f9c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda @@ -430,6 +517,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-25.11.1-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda @@ -437,10 +525,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-tree-1.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py311hdf67eae_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.11.14-py311hd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.3-py311h2005dd1_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hd9c7081_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.18-py311hc665b79_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda @@ -449,6 +541,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/editables-0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/euphonic-1.4.5-py311h0372a8f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -461,6 +554,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.61.1-py311h3778330_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/freeglut-3.2.2-ha6d2627_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/freeimage-3.18.0-h49ef1fa_24.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda @@ -468,6 +562,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/future-1.0.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-2.86.3-h5192d8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glib-tools-2.86.3-hf516916_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gmpy2-2.2.1-py311h92a432a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gst-plugins-base-1.24.11-h651a532_0.conda @@ -492,23 +588,46 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.9.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/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.context-6.0.2-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.functools-4.4.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jasper-4.2.8-he3c4edf_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/jeepney-0.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jemalloc-5.2.0-he1b5a44_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jsoncpp-1.9.6-hf42df4d_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.25.1-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.25.1-he01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-1.1.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.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_console-6.6.3-pyhd8ed1ab_1.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/jupyter_events-0.12.0-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/keyring-25.7.0-pyha804496_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.9-py311h724c32c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lame-3.100-h166bdaf_1003.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.17-h717163a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda @@ -568,6 +687,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libraw-0.21.4-h9969a89_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/librdkafka-2.11.1-hdd48ec7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsndfile-1.2.2-hc7d488a_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda @@ -594,19 +714,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py311h3778330_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.9.4-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.9.4-py311h2b939e6_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/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.8.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mpc-1.3.1-h24ddda3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mpfr-4.2.1-h90cbb55_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.32.9-hc50e24c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/muparser-2.3.4-h27087fc_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-4.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.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/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.3-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.1.3-py311h71ddf71_0.conda @@ -617,7 +748,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-he970967_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/orsopy-1.2.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda @@ -632,9 +766,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ply-3.11-pyhd8ed1ab_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/poco-1.14.2-h0a6e815_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/prettytable-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.1-py311haee01d2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pulseaudio-client-17.0-h9a6aba3_3.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/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycifrw-5.0.1-py311h49ec1c0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py311h49ec1c0_3.conda @@ -650,9 +789,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.14-hd63d673_2_cpython.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-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py311h3778330_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py311h2315fbb_0.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/qt-main-5.15.15-h3c3fd16_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.10.1-h6f76662_3.conda @@ -661,17 +804,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/quickbayes-1.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rapidjson-1.1.0.post20240409-h3f2d84a_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-py-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py311h902ca64_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py311haee01d2_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py311haee01d2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.3-py311hbe70eeb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/secretstorage-3.4.1-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/seekpath-2.1.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda @@ -680,6 +829,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/spglib-2.7.0-py311hd78beb3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx_rtd_theme-3.0.2-pyha770c72_0.conda @@ -690,8 +840,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-1.1.10-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sympy-1.14.0-pyh2585a3b_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2022.3.0-h8d10470_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda @@ -700,6 +854,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/toolz-1.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.3-py311h49ec1c0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2025.12.1.14-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.21.1-pyhf8876ea_0.conda @@ -708,10 +863,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/uncertainties-3.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.0-py311h49ec1c0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/unixodbc-2.3.14-h69e2008_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/userpath-1.9.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/uv-0.9.21-h76e24b7_0.conda @@ -719,7 +876,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.35.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.24.0-hd6090a7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.14-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-image-0.4.0-hb711507_2.conda @@ -746,6 +907,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.6-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda @@ -901,6 +1063,50 @@ packages: - pkg:pypi/argcomplete?source=hash-mapping size: 42386 timestamp: 1760975036972 +- conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + sha256: bea62005badcb98b1ae1796ec5d70ea0fc9539e7d59708ac4e7d41e2f4bb0bad + md5: 8ac12aff0860280ee0cff7fa2cf63f3b + depends: + - argon2-cffi-bindings + - python >=3.9 + - typing-extensions + constrains: + - argon2_cffi ==999 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi?source=hash-mapping + size: 18715 + timestamp: 1749017288144 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py311h49ec1c0_2.conda + sha256: b81f852f13a1d148f6ad7e2a29ab375eb1558b73c9bfa38792d98ea7fb414cff + md5: 6e36e9d2b535c3fbe2e093108df26695 + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.0.1 + - libgcc >=14 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 35831 + timestamp: 1762509453632 +- conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + sha256: 792da8131b1b53ff667bd6fc617ea9087b570305ccb9913deb36b8e12b3b5141 + md5: 85c4f19f377424eafc4ed7911b291642 + depends: + - python >=3.10 + - python-dateutil >=2.7.0 + - python-tzdata + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/arrow?source=hash-mapping + size: 113854 + timestamp: 1760831179410 - conda: https://conda.anaconda.org/conda-forge/noarch/asteval-1.0.8-pyhd8ed1ab_0.conda sha256: bf452a859eeb37a583f87e7f8eaab9a5104faf1c8322bc8ad5905165bb5b600d md5: 361b12fb5a595f025ab0289c715a56bd @@ -916,6 +1122,32 @@ packages: - pkg:pypi/asteval?source=compressed-mapping size: 27759 timestamp: 1766036175098 +- conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + sha256: ee4da0f3fe9d59439798ee399ef3e482791e48784873d546e706d0935f9ff010 + md5: 9673a61a297b00016442e022d689faa6 + depends: + - python >=3.10 + constrains: + - astroid >=2,<5 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/asttokens?source=hash-mapping + size: 28797 + timestamp: 1763410017955 +- conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.1.0-pyhcf101f3_0.conda + sha256: fb09cb9bfe4da1586d0ad3bf80bb65e70acfd5fe0f76df384250a1c0587d6acc + md5: 04d2e5fba67e5a1ecec8e25d6c769004 + depends: + - python >=3.10 + - typing_extensions >=4.0.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/async-lru?source=hash-mapping + size: 19458 + timestamp: 1768752884184 - conda: https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.2-h39aace5_0.conda sha256: a9c114cbfeda42a226e2db1809a538929d2f118ef855372293bd188f71711c48 md5: 791365c5f65975051e4e017b5da3abf5 @@ -988,6 +1220,43 @@ packages: - pkg:pypi/backports-zstd?source=hash-mapping size: 244920 timestamp: 1767044984647 +- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + sha256: bf1e71c3c0a5b024e44ff928225a0874fc3c3356ec1a0b6fe719108e6d1288f6 + md5: 5267bef8efea4127aacd1f4e1f149b6e + depends: + - python >=3.10 + - soupsieve >=1.2 + - typing-extensions + license: MIT + license_family: MIT + purls: + - pkg:pypi/beautifulsoup4?source=hash-mapping + size: 90399 + timestamp: 1764520638652 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_0.conda + sha256: e03ba1a2b93fe0383c57920a9dc6b4e0c2c7972a3f214d531ed3c21dc8f8c717 + md5: b1a27250d70881943cca0dd6b4ba0956 + depends: + - python >=3.10 + - webencodings + - python + constrains: + - tinycss >=1.1.0,<1.5 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/bleach?source=hash-mapping + size: 141952 + timestamp: 1763589981635 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-h5f6438b_0.conda + sha256: f85f6b2c7938d8c20c80ce5b7e6349fafbb49294641b5648273c5f892b150768 + md5: 08a03378bc5293c6f97637323802f480 + depends: + - bleach ==6.3.0 pyhcf101f3_0 + - tinycss2 + license: Apache-2.0 AND MIT + purls: [] + size: 4386 + timestamp: 1763589981639 - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda sha256: ea5f4c876eff2ed469551b57f1cc889a3c01128bf3e2e10b1fea11c3ef39eac2 md5: c7eb87af73750d6fd97eff8bbee8cb9c @@ -1207,6 +1476,18 @@ packages: - pkg:pypi/colorama?source=hash-mapping size: 27011 timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + sha256: 576a44729314ad9e4e5ebe055fbf48beb8116b60e58f9070278985b2b634f212 + md5: 2da13f2b299d8e1995bafbbe9689a2f7 + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/comm?source=hash-mapping + size: 14690 + timestamp: 1753453984907 - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-25.11.1-py311h38be061_0.conda sha256: f8cf33cdbae30deb7efb13bb920e15cbdaf2588c6e709f8eb18741443237157c md5: 35baaa353a5ca6814589c87672076d13 @@ -1341,6 +1622,17 @@ packages: purls: [] size: 24283 timestamp: 1756734785482 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.11.14-py311hd8ed1ab_3.conda + noarch: generic + sha256: 1ab553de31284db27705bba6ff8931b54b8d39e70d700718d6169c7f9c7c88bb + md5: 85bce7761323f3b9b0854437afde219c + depends: + - python >=3.11,<3.12.0a0 + - python_abi * *_cp311 + license: Python-2.0 + purls: [] + size: 47960 + timestamp: 1769471134936 - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-46.0.3-py311h2005dd1_1.conda sha256: 3469975e4e836ae8c40b54b4a9c514b15565450b86503244c1d11ff4c9a91932 md5: 4621dd1f3c38b24472a5e7ea4b3d8f6c @@ -1401,6 +1693,32 @@ packages: purls: [] size: 447649 timestamp: 1764536047944 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.18-py311hc665b79_0.conda + sha256: ba68335de570bc24f9bba813b8608a2822e619f4741efce194d073b48dfddcfc + md5: 0ef6a6d6c08ff139453694184efcd3dc + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2732796 + timestamp: 1765704055695 +- conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + sha256: c17c6b9937c08ad63cb20a26f403a3234088e57d4455600974a0ce865cb14017 + md5: 9ce473d1d1be1cc3810856a48b3fab32 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/decorator?source=hash-mapping + size: 14129 + timestamp: 1740385067843 - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 sha256: 9717a059677553562a8f38ff07f3b9f61727bd614f505658b0a5ecbcf8df89be md5: 961b3a227b437d82ad7054484cfa71b2 @@ -1514,6 +1832,17 @@ packages: - pkg:pypi/exceptiongroup?source=hash-mapping size: 21333 timestamp: 1763918099466 +- conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + sha256: 210c8165a58fdbf16e626aac93cc4c14dbd551a01d1516be5ecad795d2422cad + md5: ff9efb7f7469aed3c4a8106ffa29593c + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/executing?source=hash-mapping + size: 30753 + timestamp: 1756729456476 - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.2-pyhd8ed1ab_0.conda sha256: 8c4210ed4dc439e87528635e226042ddab9bf458d4d0a12e7ba48d6c5babd0f8 md5: 7e7cf4d6c2be6991e6ae2b3f4331701c @@ -1648,6 +1977,18 @@ packages: - pkg:pypi/fonttools?source=compressed-mapping size: 3004920 timestamp: 1765633180642 +- conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + sha256: 2509992ec2fd38ab27c7cdb42cf6cadc566a1cc0d1021a2673475d9fa87c6276 + md5: d3549fd50d450b6d9e7dddff25dd2110 + depends: + - cached-property >=1.3.0 + - python >=3.9,<4 + license: MPL-2.0 + license_family: MOZILLA + purls: + - pkg:pypi/fqdn?source=hash-mapping + size: 16705 + timestamp: 1733327494780 - conda: https://conda.anaconda.org/conda-forge/linux-64/freeglut-3.2.2-ha6d2627_3.conda sha256: 676540a8e7f73a894cb1fcb870e7bec623ec1c0a2d277094fd713261a02d8d56 md5: 84ec3f5b46f3076be49f2cf3f1cfbf02 @@ -1745,6 +2086,33 @@ packages: purls: [] size: 116337 timestamp: 1765221915390 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda + sha256: 309cf4f04fec0c31b6771a5809a1909b4b3154a2208f52351e1ada006f4c750c + md5: c94a5994ef49749880a8139cf9afcbe1 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: GPL-2.0-or-later OR LGPL-3.0-or-later + purls: [] + size: 460055 + timestamp: 1718980856608 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gmpy2-2.2.1-py311h92a432a_2.conda + sha256: fbe865298f27112a605284020205b2803ac913c095af5f5b10d9b7fd7dfd24dc + md5: a84186a60d84f6506b54ceb65e83d363 + depends: + - __glibc >=2.17,<3.0.a0 + - gmp >=6.3.0,<7.0a0 + - libgcc >=14 + - mpc >=1.3.1,<2.0a0 + - mpfr >=4.2.1,<5.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: LGPL-3.0-or-later + license_family: LGPL + purls: + - pkg:pypi/gmpy2?source=hash-mapping + size: 202878 + timestamp: 1762946866045 - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c md5: 2cd94587f3a401ae05e03a6caf09539d @@ -2135,6 +2503,97 @@ packages: - pkg:pypi/iniconfig?source=compressed-mapping size: 13387 timestamp: 1760831448842 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.1.0-pyha191276_0.conda + sha256: a9d6b74115dbd62e19017ff8fa4885b07b5164427f262cc15b5307e5aaf3ee73 + md5: c6f63cfe66adaa5650788e3106b6683a + depends: + - python + - __linux + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.0.0 + - jupyter_core >=4.12,!=5.0.* + - matplotlib-inline >=0.1 + - nest-asyncio >=1.4 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.2 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + size: 133820 + timestamp: 1761567932044 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.9.0-pyh53cf698_0.conda + sha256: 4ff1733c59b72cf0c8ed9ddb6e948e99fc6b79b76989282c0c7a46aab56e6176 + md5: 8481978caa2f108e6ddbf8008a345546 + depends: + - __unix + - pexpect >4.3 + - decorator >=4.3.2 + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.1 + - matplotlib-inline >=0.1.5 + - prompt-toolkit >=3.0.41,<3.1.0 + - pygments >=2.11.0 + - python >=3.11 + - stack_data >=0.6.0 + - traitlets >=5.13.0 + - typing_extensions >=4.6 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython?source=compressed-mapping + size: 646242 + timestamp: 1767621166614 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + sha256: 894682a42a7d659ae12878dbcb274516a7031bbea9104e92f8e88c1f2765a104 + md5: bd80ba060603cc228d9d81c257093119 + depends: + - pygments + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython-pygments-lexers?source=hash-mapping + size: 13993 + timestamp: 1737123723464 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.8-pyhd8ed1ab_0.conda + sha256: 6bb58afb7eabc8b4ac0c7e92707fb498313cc0164cf04e7ba1090dbf49af514b + md5: d68e3f70d1f068f1b66d94822fdc644e + depends: + - comm >=0.1.3 + - ipython >=6.1.0 + - jupyterlab_widgets >=3.0.15,<3.1.0 + - python >=3.10 + - traitlets >=4.3.1 + - widgetsnbextension >=4.0.14,<4.1.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipywidgets?source=hash-mapping + size: 114376 + timestamp: 1762040524661 +- conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + sha256: 08e838d29c134a7684bca0468401d26840f41c92267c4126d7b43a6b533b0aed + md5: 0b0154421989637d424ccf0f104be51a + depends: + - arrow >=0.15.0 + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/isoduration?source=hash-mapping + size: 19832 + timestamp: 1733493720346 - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhcf101f3_3.conda sha256: 3cc991f0f09dfd00d2626e745ba68da03e4f1dcbb7b36dd20f7a7373643cd5d5 md5: d59568bad316413c89831456e691de29 @@ -2188,6 +2647,17 @@ packages: purls: [] size: 681643 timestamp: 1754514437930 +- conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + sha256: 92c4d217e2dc68983f724aa983cca5464dcb929c566627b26a2511159667dba8 + md5: a4f4c5dc9b80bc50e0d3dc4e6e8f1bd9 + depends: + - parso >=0.8.3,<0.9.0 + - python >=3.9 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/jedi?source=hash-mapping + size: 843646 + timestamp: 1733300981994 - conda: https://conda.anaconda.org/conda-forge/noarch/jeepney-0.9.0-pyhd8ed1ab_0.conda sha256: 00d37d85ca856431c67c8f6e890251e7cc9e5ef3724a0302b8d4a101f22aa27f md5: b4b91eb14fbe2f850dd2c5fc20676c0d @@ -2239,6 +2709,17 @@ packages: - pkg:pypi/joblib?source=hash-mapping size: 226448 timestamp: 1765794135253 +- conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.13.0-pyhd8ed1ab_0.conda + sha256: ba03ca5a6db38d9f48bd30172e8c512dea7a686a5c7701c6fcdb7b3023dae2ad + md5: 8d5f66ebf832c4ce28d5c37a0e76605c + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/json5?source=hash-mapping + size: 34017 + timestamp: 1767325114901 - conda: https://conda.anaconda.org/conda-forge/linux-64/jsoncpp-1.9.6-hf42df4d_1.conda sha256: ed4b1878be103deb2e4c6d0eea3c9bdddfd7fc3178383927dce7578fb1063520 md5: 7bdc5e2cc11cb0a0f795bdad9732b0f2 @@ -2303,6 +2784,92 @@ packages: - pkg:pypi/jsonschema-specifications?source=hash-mapping size: 19236 timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.25.1-he01879c_0.conda + sha256: aef6705fe1335e6472e1b6365fcdb586356b18dceff72d8d6a315fc90e900ccf + md5: 13e31c573c884962318a738405ca3487 + depends: + - jsonschema >=4.25.1,<4.25.2.0a0 + - fqdn + - idna + - isoduration + - jsonpointer >1.13 + - rfc3339-validator + - rfc3986-validator >0.1.0 + - rfc3987-syntax >=1.1.0 + - uri-template + - webcolors >=24.6.0 + license: MIT + license_family: MIT + purls: [] + size: 4744 + timestamp: 1755595646123 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-1.1.1-pyhd8ed1ab_1.conda + sha256: b538e15067d05768d1c0532a6d9b0625922a1cce751dd6a2af04f7233a1a70e9 + md5: 9453512288d20847de4356327d0e1282 + depends: + - ipykernel + - ipywidgets + - jupyter_console + - jupyterlab + - nbconvert-core + - notebook + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter?source=hash-mapping + size: 8891 + timestamp: 1733818677113 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.0-pyhcf101f3_0.conda + sha256: 897ad2e2c2335ef3c2826d7805e16002a1fd0d509b4ae0bc66617f0e0ff07bc2 + md5: 62b7c96c6cd77f8173cc5cada6a9acaa + depends: + - importlib-metadata >=4.8.3 + - jupyter_server >=1.1.2 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-lsp?source=hash-mapping + size: 60377 + timestamp: 1756388269267 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + sha256: e402bd119720862a33229624ec23645916a7d47f30e1711a4af9e005162b84f3 + md5: 8a3d6d0523f66cf004e563a50d9392b3 + depends: + - jupyter_core >=5.1 + - python >=3.10 + - python-dateutil >=2.8.2 + - pyzmq >=25.0 + - tornado >=6.4.1 + - traitlets >=5.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-client?source=compressed-mapping + size: 112785 + timestamp: 1767954655912 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_console-6.6.3-pyhd8ed1ab_1.conda + sha256: aee0cdd0cb2b9321d28450aec4e0fd43566efcd79e862d70ce49a68bf0539bcd + md5: 801dbf535ec26508fac6d4b24adfb76e + depends: + - ipykernel >=6.14 + - ipython + - jupyter_client >=7.0.0 + - jupyter_core >=4.12,!=5.0.* + - prompt_toolkit >=3.0.30 + - pygments + - python >=3.9 + - pyzmq >=17 + - traitlets >=5.4 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-console?source=hash-mapping + size: 26874 + timestamp: 1733818130068 - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a md5: b38fe4e78ee75def7e599843ef4c1ab0 @@ -2321,6 +2888,141 @@ packages: - pkg:pypi/jupyter-core?source=hash-mapping size: 65503 timestamp: 1760643864586 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.0-pyh29332c3_0.conda + sha256: 37e6ac3ccf7afcc730c3b93cb91a13b9ae827fd306f35dd28f958a74a14878b5 + md5: f56000b36f09ab7533877e695e4e8cb0 + depends: + - jsonschema-with-format-nongpl >=4.18.0 + - packaging + - python >=3.9 + - python-json-logger >=2.0.4 + - pyyaml >=5.3 + - referencing + - rfc3339-validator + - rfc3986-validator >=0.1.1 + - traitlets >=5.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-events?source=hash-mapping + size: 23647 + timestamp: 1738765986736 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + sha256: 74c4e642be97c538dae1895f7052599dfd740d8bd251f727bce6453ce8d6cd9a + md5: d79a87dcfa726bcea8e61275feed6f83 + depends: + - anyio >=3.1.0 + - argon2-cffi >=21.1 + - jinja2 >=3.0.3 + - jupyter_client >=7.4.4 + - jupyter_core >=4.12,!=5.0.* + - jupyter_events >=0.11.0 + - jupyter_server_terminals >=0.4.4 + - nbconvert-core >=6.4.4 + - nbformat >=5.3.0 + - overrides >=5.0 + - packaging >=22.0 + - prometheus_client >=0.9 + - python >=3.10 + - pyzmq >=24 + - send2trash >=1.8.2 + - terminado >=0.8.3 + - tornado >=6.2.0 + - traitlets >=5.6.0 + - websocket-client >=1.7 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-server?source=hash-mapping + size: 347094 + timestamp: 1755870522134 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + sha256: 5eda79ed9f53f590031d29346abd183051263227dd9ee667b5ca1133ce297654 + md5: 7b8bace4943e0dc345fc45938826f2b8 + depends: + - python >=3.10 + - terminado >=0.8.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-server-terminals?source=hash-mapping + size: 22052 + timestamp: 1768574057200 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.3-pyhd8ed1ab_0.conda + sha256: 18b5bff46717023ef5e81ae6ba71b254c1aca474db32c6dc21897c46ea26fa75 + md5: 106f4e36e14797b9c2abfc3849d9e92f + depends: + - async-lru >=1.0.0 + - httpx >=0.25.0,<1 + - ipykernel >=6.5.0,!=6.30.0 + - jinja2 >=3.0.3 + - jupyter-lsp >=2.0.0 + - jupyter_core + - jupyter_server >=2.4.0,<3 + - jupyterlab_server >=2.28.0,<3 + - notebook-shim >=0.2 + - packaging + - python >=3.10 + - setuptools >=41.1.0 + - tomli >=1.2.2 + - tornado >=6.2.0 + - traitlets + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab?source=compressed-mapping + size: 8554335 + timestamp: 1769190054941 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + sha256: dc24b900742fdaf1e077d9a3458fd865711de80bca95fe3c6d46610c532c6ef0 + md5: fd312693df06da3578383232528c468d + depends: + - pygments >=2.4.1,<3 + - python >=3.9 + constrains: + - jupyterlab >=4.0.8,<5.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-pygments?source=hash-mapping + size: 18711 + timestamp: 1733328194037 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + sha256: 381d2d6a259a3be5f38a69463e0f6c5dcf1844ae113058007b51c3bef13a7cee + md5: a63877cb23de826b1620d3adfccc4014 + depends: + - babel >=2.10 + - jinja2 >=3.0.3 + - json5 >=0.9.0 + - jsonschema >=4.18 + - jupyter_server >=1.21,<3 + - packaging >=21.3 + - python >=3.10 + - requests >=2.31 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-server?source=hash-mapping + size: 51621 + timestamp: 1761145478692 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.16-pyhcf101f3_1.conda + sha256: 5c03de243d7ae6247f39a402f4785d95e61c3be79ef18738e8f17155585d31a8 + md5: dbf8b81974504fa51d34e436ca7ef389 + depends: + - python >=3.10 + - python + constrains: + - jupyterlab >=3,<5 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-widgets?source=hash-mapping + size: 216779 + timestamp: 1762267481404 - conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda sha256: 2057ca87b313bde5b74b93b0e696f8faab69acd4cb0edebb78469f3f388040c0 md5: 5aeabe88534ea4169d4c49998f293d6c @@ -2400,6 +3102,17 @@ packages: purls: [] size: 508258 timestamp: 1664996250081 +- conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + sha256: 49570840fb15f5df5d4b4464db8ee43a6d643031a2bc70ef52120a52e3809699 + md5: 9b965c999135d43a3d0f7bd7d024e26a + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/lark?source=compressed-mapping + size: 94312 + timestamp: 1761596921009 - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.17-h717163a_0.conda sha256: d6a61830a354da022eae93fa896d0991385a875c6bba53c82263a289deda9db8 md5: 000e85703f0fd9594c81710dd5066471 @@ -3189,6 +3902,15 @@ packages: purls: [] size: 355619 timestamp: 1765181778282 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda + sha256: 0105bd108f19ea8e6a78d2d994a6d4a8db16d19a41212070d2d1d48a63c34161 + md5: a587892d3c13b6621a6091be690dbca2 + depends: + - libgcc-ng >=12 + license: ISC + purls: [] + size: 205978 + timestamp: 1716828628198 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda sha256: 2fc2cdc8ea4dfd9277ae910fa3cfbf342d7890837a2002cf427fd306a869150b md5: 21769ce326958ec230cdcbd0f2ad97eb @@ -3452,10 +4174,9 @@ packages: timestamp: 1753035921043 - pypi: ./ name: lr-reduction - version: 2.9.0.dev1 - sha256: f23aa8b0be753c8e5d518c61810d32534cd0146477501c54a00fdfa5101338f9 + version: 2.9.0.dev13 + sha256: ceb0c4e4f7cfe2d643e1a278bd584bf35c775aeba147268c671ebb32e3354f3e requires_python: '>=3.11' - editable: true - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda sha256: 47326f811392a5fd3055f0f773036c392d26fdb32e4d8e7a8197eed951489346 md5: 9de5350a85c4a20c685259b889aa6393 @@ -3604,6 +4325,18 @@ packages: - pkg:pypi/matplotlib?source=hash-mapping size: 7918459 timestamp: 1734120522524 +- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + sha256: 9d690334de0cd1d22c51bc28420663f4277cfa60d34fa5cad1ce284a13f1d603 + md5: 00e120ce3e40bad7bfc78861ce3c4a25 + depends: + - python >=3.10 + - traitlets + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/matplotlib-inline?source=hash-mapping + size: 15175 + timestamp: 1761214578417 - conda: https://conda.anaconda.org/conda-forge/noarch/mdit-py-plugins-0.5.0-pyhd8ed1ab_0.conda sha256: 123cc004e2946879708cdb6a9eff24acbbb054990d6131bb94bca7a374ebebfc md5: 1997a083ef0b4c9331f9191564be275e @@ -3638,6 +4371,19 @@ packages: - pkg:pypi/menuinst?source=hash-mapping size: 186910 timestamp: 1765733175922 +- conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + sha256: d3fb4beb5e0a52b6cc33852c558e077e1bfe44df1159eb98332d69a264b14bae + md5: b11e360fc4de2b0035fc8aaa74f17fd6 + depends: + - python >=3.10 + - typing_extensions + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/mistune?source=hash-mapping + size: 74250 + timestamp: 1766504456031 - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.8.0-pyhcf101f3_1.conda sha256: 449609f0d250607a300754474350a3b61faf45da183d3071e9720e453c765b8a md5: 32f78e9d06e8593bc4bbf1338da06f5f @@ -3650,6 +4396,31 @@ packages: - pkg:pypi/more-itertools?source=hash-mapping size: 69210 timestamp: 1764487059562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mpc-1.3.1-h24ddda3_1.conda + sha256: 1bf794ddf2c8b3a3e14ae182577c624fa92dea975537accff4bc7e5fea085212 + md5: aa14b9a5196a6d8dd364164b7ce56acf + depends: + - __glibc >=2.17,<3.0.a0 + - gmp >=6.3.0,<7.0a0 + - libgcc >=13 + - mpfr >=4.2.1,<5.0a0 + license: LGPL-3.0-or-later + license_family: LGPL + purls: [] + size: 116777 + timestamp: 1725629179524 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mpfr-4.2.1-h90cbb55_3.conda + sha256: f25d2474dd557ca66c6231c8f5ace5af312efde1ba8290a6ea5e1732a4e669c0 + md5: 2eeb50cab6652538eee8fc0bc3340c81 + depends: + - __glibc >=2.17,<3.0.a0 + - gmp >=6.3.0,<7.0a0 + - libgcc >=13 + license: LGPL-3.0-only + license_family: LGPL + purls: [] + size: 634751 + timestamp: 1725746740014 - conda: https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.32.9-hc50e24c_0.conda sha256: 39c4700fb3fbe403a77d8cc27352fa72ba744db487559d5d44bf8411bb4ea200 md5: c7f302fd11eeb0987a6a5e1f3aed6a21 @@ -3662,6 +4433,17 @@ packages: purls: [] size: 491140 timestamp: 1730581373280 +- conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda + sha256: 7d7aa3fcd6f42b76bd711182f3776a02bef09a68c5f117d66b712a6d81368692 + md5: 3585aa87c43ab15b167b574cd73b057b + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/mpmath?source=hash-mapping + size: 439705 + timestamp: 1733302781386 - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda sha256: 8c81a6208def64afc3e208326d78d7af60bcbc32d44afe1269b332df84084f29 md5: c1153b2cb3318889ce624a3b4f0db7f7 @@ -3728,6 +4510,51 @@ packages: - pkg:pypi/narwhals?source=compressed-mapping size: 272452 timestamp: 1767693390284 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + sha256: 1b66960ee06874ddceeebe375d5f17fb5f393d025a09e15b830ad0c4fffb585b + md5: 00f5b8dafa842e0c27c1cd7296aa4875 + depends: + - jupyter_client >=6.1.12 + - jupyter_core >=4.12,!=5.0.* + - nbformat >=5.1 + - python >=3.8 + - traitlets >=5.4 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbclient?source=compressed-mapping + size: 28473 + timestamp: 1766485646962 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyhcf101f3_1.conda + sha256: 8f575e5c042b17f4677179a6ba474bdbe76573936d3d3e2aeb42b511b9cb1f3f + md5: cfc86ccc3b1de35d36ccaae4c50391f5 + depends: + - beautifulsoup4 + - bleach-with-css !=5.0.0 + - defusedxml + - importlib-metadata >=3.6 + - jinja2 >=3.0 + - jupyter_core >=4.7 + - jupyterlab_pygments + - markupsafe >=2.0 + - mistune >=2.0.3,<4 + - nbclient >=0.5.0 + - nbformat >=5.7 + - packaging + - pandocfilters >=1.4.1 + - pygments >=2.4.1 + - python >=3.10 + - traitlets >=5.1 + - python + constrains: + - pandoc >=2.9.2,<4.0.0 + - nbconvert ==7.16.6 *_1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbconvert?source=compressed-mapping + size: 199273 + timestamp: 1760797634443 - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda sha256: 7a5bd30a2e7ddd7b85031a5e2e14f290898098dc85bea5b3a5bf147c25122838 md5: bbe1963f1e47f594070ffe87cdf612ea @@ -3753,6 +4580,17 @@ packages: purls: [] size: 891641 timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + sha256: bb7b21d7fd0445ddc0631f64e66d91a179de4ba920b8381f29b9d006a42788c0 + md5: 598fd7d4d0de2455fb74f56063969a97 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/nest-asyncio?source=hash-mapping + size: 11543 + timestamp: 1733325673691 - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 md5: a2c1eeadae7a309daed9d62c96012a2b @@ -3790,6 +4628,35 @@ packages: - pkg:pypi/nodeenv?source=hash-mapping size: 40866 timestamp: 1766261270149 +- conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.5.3-pyhcf101f3_0.conda + sha256: 014cf291843861b20cf84a89e8450f0dd13ad1e6d2ab30c56ae43b81f2dca233 + md5: 94a5f0cee51b6b0ffdcad0af6db0af18 + depends: + - importlib_resources >=5.0 + - jupyter_server >=2.4.0,<3 + - jupyterlab >=4.5.3,<4.6 + - jupyterlab_server >=2.28.0,<3 + - notebook-shim >=0.2,<0.3 + - python >=3.10 + - tornado >=6.2.0 + - python + license: BSD-3-Clause + purls: + - pkg:pypi/notebook?source=compressed-mapping + size: 10047711 + timestamp: 1769434091366 +- conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + sha256: 7b920e46b9f7a2d2aa6434222e5c8d739021dbc5cc75f32d124a8191d86f9056 + md5: e7f89ea5f7ea9401642758ff50a2d9c1 + depends: + - jupyter_server >=1.8,<3 + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/notebook-shim?source=hash-mapping + size: 16817 + timestamp: 1733408419340 - conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda sha256: e3664264bd936c357523b55c71ed5a30263c6ba278d726a75b1eb112e6fb0b64 md5: e235d5566c9cc8970eb2798dd4ecf62f @@ -3942,6 +4809,18 @@ packages: - pkg:pypi/orsopy?source=hash-mapping size: 1450066 timestamp: 1736288858637 +- conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c + md5: e51f1e4089cad105b6cac64bd8166587 + depends: + - python >=3.9 + - typing_utils + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/overrides?source=hash-mapping + size: 30139 + timestamp: 1734587755455 - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991 md5: 58335b26c38bf4a20f399384c33cbcf9 @@ -3954,6 +4833,29 @@ packages: - pkg:pypi/packaging?source=hash-mapping size: 62477 timestamp: 1745345660407 +- conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + sha256: 2bb9ba9857f4774b85900c2562f7e711d08dd48e2add9bee4e1612fbee27e16f + md5: 457c2c8c08e54905d6954e79cb5b5db9 + depends: + - python !=3.0,!=3.1,!=3.2,!=3.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pandocfilters?source=hash-mapping + size: 11627 + timestamp: 1631603397334 +- conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.5-pyhcf101f3_0.conda + sha256: 30de7b4d15fbe53ffe052feccde31223a236dae0495bab54ab2479de30b2990f + md5: a110716cdb11cf51482ff4000dc253d7 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/parso?source=hash-mapping + size: 81562 + timestamp: 1755974222274 - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.0-pyhd8ed1ab_0.conda sha256: 1493d56d7a02bdcaacc28a4fc2c1249230a6cf24750608e2b30bdf5c9154bb70 md5: c27944cfd04162af4832834f5f110bd0 @@ -4161,6 +5063,55 @@ packages: - pkg:pypi/prettytable?source=hash-mapping size: 35808 timestamp: 1763199361018 +- conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.24.1-pyhd8ed1ab_0.conda + sha256: 75b2589159d04b3fb92db16d9970b396b9124652c784ab05b66f584edc97f283 + md5: 7526d20621b53440b0aae45d4797847e + depends: + - python >=3.10 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/prometheus-client?source=compressed-mapping + size: 56634 + timestamp: 1768476602855 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + sha256: 4817651a276016f3838957bfdf963386438c70761e9faec7749d411635979bae + md5: edb16f14d920fb3faf17f5ce582942d6 + depends: + - python >=3.10 + - wcwidth + constrains: + - prompt_toolkit 3.0.52 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/prompt-toolkit?source=hash-mapping + size: 273927 + timestamp: 1756321848365 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.52-hd8ed1ab_0.conda + sha256: e79922a360d7e620df978417dd033e66226e809961c3e659a193f978a75a9b0b + md5: 6d034d3a6093adbba7b24cb69c8c621e + depends: + - prompt-toolkit >=3.0.52,<3.0.53.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 7212 + timestamp: 1756321849562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.1-py311haee01d2_0.conda + sha256: 3ff5620fe75ff73b2aa61f6199bf46872b49664d8e7c5d12c2ff6fee14456291 + md5: 8cc656ea4773e02929cc58745669b116 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 228910 + timestamp: 1767012395880 - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 md5: b3c17d95b5a10c6e64a21fa17573e70e @@ -4201,6 +5152,17 @@ packages: purls: [] size: 750785 timestamp: 1763148198088 +- conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + sha256: 71bd24600d14bb171a6321d523486f6a06f855e75e547fa0cb2a0953b02047f0 + md5: 3bfdfb8dbcdc4af1ae3f9a8eb3948f04 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pure-eval?source=hash-mapping + size: 16668 + timestamp: 1733569518868 - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda sha256: 9e7fe12f727acd2787fb5816b2049cef4604b7a00ad3e408c5e709c298ce8bf1 md5: f0599959a2447c1e544e216bddf393fa @@ -4525,6 +5487,28 @@ packages: - pkg:pypi/fastjsonschema?source=hash-mapping size: 244628 timestamp: 1755304154927 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda + sha256: 4790787fe1f4e8da616edca4acf6a4f8ed4e7c6967aa31b920208fc8f95efcca + md5: a61bf9ec79426938ff785eb69dbb1960 + depends: + - python >=3.6 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/python-json-logger?source=hash-mapping + size: 13383 + timestamp: 1677079727691 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda + sha256: 467134ef39f0af2dbb57d78cb3e4821f01003488d331a8dd7119334f4f47bfbd + md5: 7ead57407430ba33f681738905278d03 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/tzdata?source=compressed-mapping + size: 143542 + timestamp: 1765719982349 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda build_number: 8 sha256: fddf123692aa4b1fc48f0471e346400d9852d96eeed77dbfdd746fa50a8ff894 @@ -4562,6 +5546,22 @@ packages: - pkg:pypi/pyyaml?source=hash-mapping size: 211606 timestamp: 1758892088237 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py311h2315fbb_0.conda + sha256: 719104f31c414166a20281c973b6e29d1a2ab35e7930327368949895b8bc5629 + md5: 6c87a0f4566469af3585b11d89163fd7 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + - zeromq >=4.3.5,<4.4.0a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 386618 + timestamp: 1757387012835 - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda sha256: 776363493bad83308ba30bcb88c2552632581b143e8ee25b1982c8c743e73abc md5: 353823361b1d27eb3960efb076dfcaf6 @@ -4850,6 +5850,42 @@ packages: - pkg:pypi/requests-toolbelt?source=hash-mapping size: 44285 timestamp: 1733734886897 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + sha256: 2e4372f600490a6e0b3bac60717278448e323cab1c0fecd5f43f7c56535a99c5 + md5: 36de09a8d3e5d5e6f4ee63af49e59706 + depends: + - python >=3.9 + - six + license: MIT + license_family: MIT + purls: + - pkg:pypi/rfc3339-validator?source=hash-mapping + size: 10209 + timestamp: 1733600040800 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + sha256: 2a5b495a1de0f60f24d8a74578ebc23b24aa53279b1ad583755f223097c41c37 + md5: 912a71cc01012ee38e6b90ddd561e36f + depends: + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/rfc3986-validator?source=hash-mapping + size: 7818 + timestamp: 1598024297745 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + sha256: 70001ac24ee62058557783d9c5a7bbcfd97bd4911ef5440e3f7a576f9e43bc92 + md5: 7234f99325263a5af6d4cd195035e8f2 + depends: + - python >=3.9 + - lark >=1.2.2 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/rfc3987-syntax?source=hash-mapping + size: 22913 + timestamp: 1752876729969 - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda sha256: edfb44d0b6468a8dfced728534c755101f06f1a9870a7ad329ec51389f16b086 md5: a247579d8a59931091b16a1e932bbed6 @@ -4998,6 +6034,19 @@ packages: - pkg:pypi/seekpath?source=hash-mapping size: 56120 timestamp: 1755759152086 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_0.conda + sha256: b25d573874fe39cb8e4cf6ed0279acb9a94fedce5c5ae885da11566d595035ad + md5: 645026465469ecd4989188e1c4e24953 + depends: + - __linux + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/send2trash?source=hash-mapping + size: 23960 + timestamp: 1768402421616 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda sha256: 972560fcf9657058e3e1f97186cc94389144b46dbdf58c807ce62e83f977e863 md5: 4de79c071274a53dcaf2a8c749d1499e @@ -5101,6 +6150,17 @@ packages: - pkg:pypi/snowballstemmer?source=hash-mapping size: 73009 timestamp: 1747749529809 +- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + sha256: 23b71ecf089967d2900126920e7f9ff18cdcef82dbff3e2f54ffa360243a17ac + md5: 18de09b20462742fe093ba39185d9bac + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/soupsieve?source=hash-mapping + size: 38187 + timestamp: 1769034509657 - conda: https://conda.anaconda.org/conda-forge/linux-64/spglib-2.7.0-py311hd78beb3_1.conda sha256: a194211acf3d7d72d8f2866eb328694afdea27ffb8e43c7f727bcdb2d9834ac1 md5: 2d6d1fca5d1936df8d83b69782fdc1b2 @@ -5245,6 +6305,35 @@ packages: - pkg:pypi/sphinxcontrib-serializinghtml?source=hash-mapping size: 28669 timestamp: 1733750596111 +- conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + sha256: 570da295d421661af487f1595045760526964f41471021056e993e73089e9c41 + md5: b1b505328da7a6b246787df4b5a49fbc + depends: + - asttokens + - executing + - pure_eval + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/stack-data?source=hash-mapping + size: 26988 + timestamp: 1733569565672 +- conda: https://conda.anaconda.org/conda-forge/noarch/sympy-1.14.0-pyh2585a3b_105.conda + sha256: 09d3b6ac51d437bc996ad006d9f749ca5c645c1900a854a6c8f193cbd13f03a8 + md5: 8c09fac3785696e1c477156192d64b91 + depends: + - __unix + - cpython + - gmpy2 >=2.0.8 + - mpmath >=0.19 + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/sympy?source=hash-mapping + size: 4616621 + timestamp: 1745946173026 - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2022.3.0-h8d10470_1.conda sha256: 2e3238234ae094d5a5f7c559410ea8875351b6bac0d9d0e576bf64b732b8029e md5: e3259be3341da4bc06c5b7a78c8bf1bd @@ -5258,6 +6347,21 @@ packages: purls: [] size: 181262 timestamp: 1762509955687 +- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + sha256: 6b6727a13d1ca6a23de5e6686500d0669081a117736a87c8abf444d60c1e40eb + md5: 17b43cee5cc84969529d5d0b0309b2cb + depends: + - __unix + - ptyprocess + - python >=3.10 + - tornado >=6.1.0 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/terminado?source=hash-mapping + size: 24749 + timestamp: 1766513766867 - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda sha256: 6016672e0e72c4cf23c0cf7b1986283bd86a9c17e8d319212d78d8e9ae42fdfd md5: 9d64911b31d57ca443e9f1e36b04385f @@ -5269,6 +6373,19 @@ packages: - pkg:pypi/threadpoolctl?source=hash-mapping size: 23869 timestamp: 1741878358548 +- conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.5.1-pyhcf101f3_0.conda + sha256: 7c803480dbfb8b536b9bf6287fa2aa0a4f970f8c09075694174eb4550a4524cd + md5: c0d0b883e97906f7524e2aac94be0e0d + depends: + - python >=3.10 + - webencodings >=0.4 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/tinycss2?source=compressed-mapping + size: 30571 + timestamp: 1764621508086 - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda sha256: 1544760538a40bcd8ace2b1d8ebe3eb5807ac268641f8acdc18c69c5ebfeaf64 md5: 86bc20552bf46075e3d92b67f089172d @@ -5483,6 +6600,17 @@ packages: - pkg:pypi/typing-extensions?source=hash-mapping size: 51692 timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + sha256: 3088d5d873411a56bf988eee774559335749aed6f6c28e07bf933256afb9eb6c + md5: f6d7aa696c67756a650e91e15e88223c + depends: + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/typing-utils?source=hash-mapping + size: 15183 + timestamp: 1733331395943 - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c md5: ad659d0a2b3e47e38d829aa8cad2d610 @@ -5546,6 +6674,17 @@ packages: purls: [] size: 307887 timestamp: 1764772751439 +- conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + sha256: e0eb6c8daf892b3056f08416a96d68b0a358b7c46b99c8a50481b22631a4dfc0 + md5: e7cb0f5745e4c5035a460248334af7eb + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/uri-template?source=hash-mapping + size: 23990 + timestamp: 1733323714454 - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.2-pyhd8ed1ab_0.conda sha256: f4302a80ee9b76279ad061df05003abc2a29cc89751ffab2fd2919b43455dac0 md5: 4949ca7b83065cfe94ebe320aece8c72 @@ -5640,6 +6779,39 @@ packages: - pkg:pypi/wcwidth?source=hash-mapping size: 33670 timestamp: 1758622418893 +- conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + sha256: 21f6c8a20fe050d09bfda3fb0a9c3493936ce7d6e1b3b5f8b01319ee46d6c6f6 + md5: 6639b6b0d8b5a284f027a2003669aa65 + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/webcolors?source=hash-mapping + size: 18987 + timestamp: 1761899393153 +- conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + sha256: 19ff205e138bb056a46f9e3839935a2e60bd1cf01c8241a5e172a422fed4f9c6 + md5: 2841eb5bfc75ce15e9a0054b98dcd64d + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/webencodings?source=hash-mapping + size: 15496 + timestamp: 1733236131358 +- conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + sha256: 42a2b61e393e61cdf75ced1f5f324a64af25f347d16c60b14117393a98656397 + md5: 2f1ed718fcd829c184a6d4f0f2e07409 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/websocket-client?source=hash-mapping + size: 61391 + timestamp: 1759928175142 - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda sha256: 1b34021e815ff89a4d902d879c3bd2040bc1bd6169b32e9427497fa05c55f1ce md5: 75cb7132eb58d97896e173ef12ac9986 @@ -5651,6 +6823,17 @@ packages: - pkg:pypi/wheel?source=hash-mapping size: 62931 timestamp: 1733130309598 +- conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.15-pyhd8ed1ab_0.conda + sha256: 826af5e2c09e5e45361fa19168f46ff524e7a766022615678c3a670c45895d9a + md5: dc257b7e7cad9b79c1dfba194e92297b + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/widgetsnbextension?source=hash-mapping + size: 889195 + timestamp: 1762040404362 - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda sha256: ad8cab7e07e2af268449c2ce855cbb51f43f4664936eff679b1f3862e6e4b01d md5: fdc27cb255a7a2cc73b7919a968b48f0 @@ -5974,6 +7157,21 @@ packages: purls: [] size: 223526 timestamp: 1745307989800 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda + sha256: 47cfe31255b91b4a6fa0e9dbaf26baa60ac97e033402dbc8b90ba5fee5ffe184 + md5: 8035e5b54c08429354d5d64027041cad + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libsodium >=1.0.20,<1.0.21.0a0 + - krb5 >=1.21.3,<1.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 310648 + timestamp: 1757370847287 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae md5: 30cd29cb87d819caead4d55184c1d115 diff --git a/pyproject.toml b/pyproject.toml index 6f473a30..c281c571 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,6 +87,8 @@ matplotlib = "==3.9.4" plot-publisher = ">=1.0,<2.0" pyqt = ">=5,<6" qtpy = ">=2.4.3" +sympy = ">=1.14.0,<2" +jupyter = ">=1.1.1,<2" # Pypi packages to be installed in the environments with `pip` [tool.pixi.pypi-dependencies] @@ -102,6 +104,7 @@ matplotlib = "==3.9.4" plot-publisher = ">=1.0,<2.0" pyqt = ">=5,<6" qtpy = ">=2.4.3" +sympy = ">=1.14.0,<2" [tool.pixi.package] name = "lr_reduction" diff --git a/src/lr_reduction/data_info.py b/src/lr_reduction/data_info.py index ce017c69..6731e8c5 100644 --- a/src/lr_reduction/data_info.py +++ b/src/lr_reduction/data_info.py @@ -37,23 +37,66 @@ def from_workspace(cls, input_workspace: MantidWorkspace): sample_logs = SampleLogValues(input_workspace) value = cls.REFLECTED_BEAM try: + coordinate_system = CoordinateSystem.from_workspace(input_workspace) # Determine whether this is a direct beam based on the geometry - if (("BL4B:CS:Mode:Coordinates" in sample_logs and sample_logs["BL4B:CS:Mode:Coordinates"] == 0) or # This is a new log for earth-centered - sample_logs["BL4B:CS:ExpPl:OperatingMode"] == "Free Liquid"): # This is for backward compatibility from before the new log value - # Earth-centered coordinate system + if coordinate_system == CoordinateSystem.EARTH_CENTERED: thi = sample_logs["thi"] tthd = sample_logs["tthd"] if np.isclose(thi, tthd, atol=0.01): value = cls.DIRECT_BEAM - else: + elif coordinate_system == CoordinateSystem.BEAM_CENTERED: # Beam-centered coordinate system ths = sample_logs["ths"] tthd = sample_logs["tthd"] if np.fabs(tthd) < 0.001 and np.fabs(ths) < 0.001: value = cls.DIRECT_BEAM - except KeyError as e: + else: + logger.warning("Unknown coordinate system; assuming reflected beam") + except RuntimeError as e: logger.warning(f"Missing sample log {e}, assuming reflected beam") return value def __str__(self): return self.name + + +class CoordinateSystem(IntEnum): + """ + Enum to represent the coordinate system used in the experiment. + + Attributes: + UNKNOWN (int): Represents unknown coordinate system. + EARTH_CENTERED (int): Represents the Earth-centered coordinate system. + BEAM_CENTERED (int): Represents the Beam-centered coordinate system. + """ + + UNKNOWN = -1 + EARTH_CENTERED = 0 + BEAM_CENTERED = 1 + + @classmethod + def from_workspace(cls, input_workspace: MantidWorkspace): + """ + Determine the coordinate system from the given workspace. + """ + sample_logs = SampleLogValues(input_workspace) + value = cls.UNKNOWN + try: + # This is the new log for coordinate system mode + if "BL4B:CS:Mode:Coordinates" in sample_logs: + if sample_logs["BL4B:CS:Mode:Coordinates"] == 0: + value = cls.EARTH_CENTERED + else: + value = cls.BEAM_CENTERED + # Fallback to older method using operating mode + elif "BL4B:CS:ExpPl:OperatingMode" in sample_logs: + if sample_logs["BL4B:CS:ExpPl:OperatingMode"] == "Free Liquid": + value = cls.EARTH_CENTERED + else: + value = cls.BEAM_CENTERED + except RuntimeError as e: + logger.warning(f"Missing sample log {e}, unable to determine coordinate system") + return value + + def __str__(self): + return self.name diff --git a/src/lr_reduction/event_reduction.py b/src/lr_reduction/event_reduction.py index 284eaf90..ae397e4b 100644 --- a/src/lr_reduction/event_reduction.py +++ b/src/lr_reduction/event_reduction.py @@ -12,8 +12,11 @@ import numpy as np from scipy.optimize import brentq +from lr_reduction.data_info import CoordinateSystem from lr_reduction.gravity_correction import GravityDirection, gravity_correction from lr_reduction.instrument_settings import InstrumentSettings +from lr_reduction.types import MantidWorkspace +from lr_reduction.user_defined_function import UserDefinedFunction from lr_reduction.utils import mantid_algorithm_exec from . import background, dead_time_correction @@ -573,7 +576,6 @@ def to_dict(self): norm_run=norm_run, time=time.ctime(), dq0=dq0, - dq_over_q=self.dq_over_q, sequence_number=sequence_number, sequence_id=sequence_id, q_summing=self.q_summing, @@ -608,6 +610,8 @@ def specular(self, q_summing=False, tof_weighted=False, bck_in_q=False, clean=Fa The reflectivity values d_refl The uncertainties in the reflectivity values + dq_over_q_bins + The Q resolution associated with the q_bins """ if tof_weighted: self.specular_weighted(q_summing=q_summing, bck_in_q=bck_in_q) @@ -631,12 +635,13 @@ def specular(self, q_summing=False, tof_weighted=False, bck_in_q=False, clean=Fa self.d_refl = self.d_refl[idx[:-1]] self.q_bins = self.q_bins[idx] - # Compute Q resolution - self.dq_over_q = compute_resolution(self._ws_sc, theta=self.theta, q_summing=q_summing) - # TODO: integrate wavelength component to self.dq_over_q self.q_summing = q_summing - return self.q_bins, self.refl, self.d_refl + # Compute Q resolution + # For now keep the dq_over_q the same length as the q_bins to ensure conversion to mid-points is the same. + lambda_bin_list = 4 * np.pi * np.sin(self.theta) / self.q_bins + dq_over_q_bins = compute_resolution(self._ws_sc, wl_list=lambda_bin_list, theta=self.theta, q_summing=q_summing) + return self.q_bins, self.refl, self.d_refl, dq_over_q_bins def specular_unweighted(self, q_summing=False, normalize=True): """ @@ -1264,44 +1269,60 @@ def emission_time_correction(self, ws, tofs): return tofs -def compute_resolution(ws, default_dq=0.027, theta=None, q_summing=False): +def compute_theta_resolution(ws: MantidWorkspace, default_dq: float=0.027, theta: float=None, q_summing: bool=False) -> tuple[float, float]: """ - Compute the Q resolution from the meta data. + Compute the theta component of the q resolution. Corrected to include both slits. Parameters ---------- ws : mantid.api.Workspace Mantid workspace to extract correction meta-data from. + default_dq : float + Default dth/th value to use if resolution cannot be computed from logs. theta : float - Scattering angle in radians + Scattering angle in radians. If not provided will read ths or thi from ws. q_summing : bool If True, the pixel size will be used for the resolution Returns ------- - float - The dQ/Q resolution (FWHM) + tuple[float, float] + The theta and dtheta values in degrees """ settings = read_settings(ws) if theta is None: - theta = abs(ws.getRun().getProperty("ths").value[0]) * np.pi / 180.0 + coordinate_system = CoordinateSystem.from_workspace(ws) + if coordinate_system == CoordinateSystem.EARTH_CENTERED: + Theta_deg = abs(ws.getRun().getProperty("thi").value[0]) + theta = np.radians(Theta_deg) + else: + Theta_deg = abs(ws.getRun().getProperty("ths").value[0]) + theta = np.radians(Theta_deg) if q_summing: - # Q resolution is reported as FWHM, so here we consider this to be - # related to the pixel width + # Compute pixel contribution to angular resolution sdd = 1830 if settings.sample_detector_distance: sdd = settings.sample_detector_distance * 1000 - pixel_size = 0.7 + pixel_size = 0.7 # mm, default pixel size for BL4B if settings.pixel_width: pixel_size = settings.pixel_width - # All angles here in radians, assuming small angles - dq_over_q = np.arcsin(pixel_size / sdd) / theta - print("Q summing: %g" % dq_over_q) - return dq_over_q + det_res = 1.0 # mm, approximate value for detector resolution contribution + # Standard deviation of a top-hat function (uniform distribution) + sigma_pix = pixel_size / np.sqrt(12) + sigma_y = np.sqrt((det_res ** 2 + sigma_pix ** 2)) + + dtheta = np.arctan(sigma_y / sdd) # in radians + + # Want to export in degrees + dtheta_deg = np.degrees(dtheta) + theta_deg = np.degrees(theta) + + #print("Q summing: %g" % dq_over_q) ## Work out some print functions throughout. + return theta_deg, dtheta_deg # We can't compute the resolution if the value of xi is not in the logs. # Since it was not always logged, check for it here. @@ -1309,26 +1330,37 @@ def compute_resolution(ws, default_dq=0.027, theta=None, q_summing=False): # For old data, the resolution can't be computed, so use # the standard value for the instrument print("Could not find BL4B:Mot:xi.RBV: using supplied dQ/Q") - return default_dq + theta_deg = np.degrees(theta) + return theta_deg, default_dq - # Xi reference would be the position of xi if the si slit were to be positioned - # at the sample. The distance from the sample to si is then xi_reference - xi. - xi_reference = 445 - if ws.getInstrument().hasParameter("xi-reference"): - xi_reference = ws.getInstrument().getNumberParameter("xi-reference")[0] + # Compute the trapezoidal equivalent sigma of the angular distribution + theta_deg = np.degrees(theta) + _, _, _, dth_over_th = trapezoidal_distribution_params( + ws, Theta_deg=theta_deg + ) + dtheta_deg = dth_over_th * theta_deg - # Distance between the s1 and the sample - s1_sample_distance = 1485 - if settings.s1_sample_distance is not None: - s1_sample_distance = settings.s1_sample_distance * 1000 - - # Get slit gap openings. - s1h = abs(ws.getRun().getProperty("S1VHeight").value[0]) - sih = abs(ws.getRun().getProperty("SiVHeight").value[0]) - xi = abs(ws.getRun().getProperty("BL4B:Mot:xi.RBV").value[0]) - sample_si_distance = xi_reference - xi - slit_distance = s1_sample_distance - sample_si_distance - dq_over_q = (s1h + sih) * 0.5 / slit_distance / theta + return theta_deg, dtheta_deg + + +def compute_resolution(ws: MantidWorkspace, wl_list: np.ndarray, theta: float=None, q_summing: bool=False) -> np.ndarray: + """ + Compute the q resolution including both theta and lambda terms. + + :param ws: workspace for meta-data. If this is a lambda workspace + already it can be used as the lambda imports in place of the wl_list. + :param wl_list: Provide a list of wavelengths for the lambda calculation. + :param theta: option to overwrite theta input, otherwise uses ths/thi value. + :param q_summing: Changes the angular calculation to be based on slits or pixel sizes depending on method of q conversion. + """ + ## Need to check through all the None's etc. + ## Need to check separate outputs... + theta_deg, delta_th_deg = compute_theta_resolution(ws, theta=theta, q_summing=q_summing) + + wl_resolution_function = read_settings(ws).wavelength_resolution_function + lambda_list, delta_lam = compute_wavelength_resolution(wl_list, wl_resolution_function) + + dq_over_q = np.sqrt((delta_lam / lambda_list) ** 2 + (delta_th_deg / theta_deg) ** 2) return dq_over_q @@ -1347,7 +1379,7 @@ def trapezoidal_distribution_params(ws, Theta_deg=None, FootPrint=None, SlitRati ws : mantid.api.Workspace Mantid workspace to extract correction meta-data from. Theta_deg : float - Incident beam angle in degrees. + Incident beam angle in degrees. If not provided will read ths or thi from ws. FootPrint : float (optional) Beam footprint length on sample [mm]. SlitRatio : float (optional) @@ -1385,7 +1417,11 @@ def trapezoidal_distribution_params(ws, Theta_deg=None, FootPrint=None, SlitRati dS1Si = dS1Samp - dSiSamp if Theta_deg is None: - Theta_deg = abs(ws.getRun().getProperty("ths").value[0]) + coordinate_system = CoordinateSystem.from_workspace(ws) + if coordinate_system == CoordinateSystem.EARTH_CENTERED: + Theta_deg = abs(ws.getRun().getProperty("thi").value[0]) + else: + Theta_deg = abs(ws.getRun().getProperty("ths").value[0]) # Slit openings - can be taken from a FootPrint and SlitRatio if provided, or the logs if FootPrint is not None and SlitRatio is not None: @@ -1449,37 +1485,30 @@ def func(x): ## Fix q-bin error and auto trimming points -def compute_wavelength_resolution(ws): +def compute_wavelength_resolution(wl_list: np.ndarray, resolution_function_str: str) -> tuple[np.ndarray, np.ndarray]: """ - Compute the wavelength resolution from the meta data. + Compute the wavelength resolution using the given resolution function. Parameters ---------- - ws : mantid.api.Workspace - Mantid workspace to extract correction meta-data from. + wl_list : np.ndarray + Wavelength values to compute the resolution for. + resolution_function_str : str + User-defined resolution function. Returns ------- tuple of np.ndarray (wavelength, d_lambda): - wavelength: the fitted wavelength values - d_lambda: the difference between wavelength and the fit - - Raises - ------ - ValueError : if ws does not have exactly one spectrum + wavelength: the wavelength values + d_lambda: the wavelength resolution values """ + # Parse user-defined resolution function + resolution_function = UserDefinedFunction(resolution_function_str) + d_lambda = np.array(resolution_function(wl_list)) + wavelength = np.array(wl_list) - if ws.spectrumInfo().size() != 1: - raise ValueError("Workspace must have only one spectrum") - - settings = read_settings(ws) - - out = api.EvaluateFunction( - Function=settings.wavelength_resolution_function, InputWorkspace=ws, OutputWorkspace="out" - ) - - wavelength = out.readX(1) - d_lambda = out.readY(1) + # Set any negative values to zero + d_lambda[d_lambda < 0] = 0 - return np.array(wavelength), np.array(d_lambda) + return wavelength, d_lambda diff --git a/src/lr_reduction/gravity_correction.py b/src/lr_reduction/gravity_correction.py index 94d4c53d..05c968b2 100644 --- a/src/lr_reduction/gravity_correction.py +++ b/src/lr_reduction/gravity_correction.py @@ -2,6 +2,7 @@ import numpy as np +from lr_reduction.data_info import CoordinateSystem from lr_reduction.types import MantidWorkspace from lr_reduction.utils import workspace_handle @@ -94,15 +95,11 @@ def _theta_in(workspace: MantidWorkspace) -> float: # Angle calculated from thi and a flag on earth-centered vs beam-centered thi = _log_value(run, "BL4B:Mot:thi.RBV") - if "BL4B:CS:Mode:Coordinates" in run: - if _log_value(run, "BL4B:CS:Mode:Coordinates") == 0: # Earth-centered=0 - theta_in = thi - else: - theta_in = thi - 4.0 # Beamline optics gives -4 deg incline. In future will have PV. - elif _log_value(run, "BL4B:CS:ExpPl:OperatingMode", default="") == "Free Liquid": + coordinate_system = CoordinateSystem.from_workspace(workspace) + if coordinate_system == CoordinateSystem.EARTH_CENTERED: theta_in = thi else: - theta_in = thi - 4.0 + theta_in = thi - 4.0 # Beamline optics gives -4 deg incline. In future will have PV. return abs(theta_in) diff --git a/src/lr_reduction/output.py b/src/lr_reduction/output.py index c3ab511e..11b20052 100644 --- a/src/lr_reduction/output.py +++ b/src/lr_reduction/output.py @@ -165,7 +165,7 @@ def merge(self): self.d_refl_all = np.asarray(d_refl_all) self.d_qz_all = np.asarray(d_qz_all) - def save_ascii(self, file_path, meta_as_json=False): + def save_ascii(self, file_path, meta_as_json=False, fwhm=False): """ Save R(Q) in ASCII format. This function merges the data before saving. It writes metadata and R(Q) data @@ -179,6 +179,8 @@ def save_ascii(self, file_path, meta_as_json=False): The path to the file where the ASCII data will be saved. meta_as_json : bool, optional If True, metadata will be written in JSON format. Default is False. + fwhm: bool, optional + If True, dq column is labelled on output as FWHM otherwise labeled as sigma. """ self.calculate_scale_factors() self.merge() @@ -234,7 +236,10 @@ def save_ascii(self, file_path, meta_as_json=False): initial_entry_written = True # Write R(q) - fd.write("# %-21s %-21s %-21s %-21s\n" % ("Q [1/Angstrom]", "R", "dR", "dQ [FWHM]")) + if fwhm: + fd.write("# %-21s %-21s %-21s %-21s\n" % ("Q [1/Angstrom]", "R", "dR", "dQ [FWHM]")) + else: + fd.write("# %-21s %-21s %-21s %-21s\n" % ("Q [1/Angstrom]", "R", "dR", "dQ [Resolution as Sigma]")) fd.writelines( "%20.16f %20.16f %20.16f %20.16f\n" % (self.qz_all[i], self.refl_all[i], self.d_refl_all[i], self.d_qz_all[i]) diff --git a/src/lr_reduction/template.py b/src/lr_reduction/template.py index e56c67bc..a0e135d7 100644 --- a/src/lr_reduction/template.py +++ b/src/lr_reduction/template.py @@ -11,6 +11,7 @@ from mantid.simpleapi import logger from lr_reduction import event_reduction, peak_finding, reduction_template_reader +from lr_reduction.data_info import CoordinateSystem from lr_reduction.instrument_settings import InstrumentSettings from lr_reduction.reduction_template_reader import ReductionParameters from lr_reduction.types import MantidWorkspace @@ -262,10 +263,8 @@ def process_from_template_ws( if theta_value is not None: theta = theta_value * np.pi / 180.0 else: - if ( - "BL4B:CS:ExpPl:OperatingMode" in ws_sc.getRun() - and ws_sc.getRun().getProperty("BL4B:CS:ExpPl:OperatingMode").value[0] == "Free Liquid" - ): + coordinate_system = CoordinateSystem.from_workspace(ws_sc) + if coordinate_system == CoordinateSystem.EARTH_CENTERED: theta = thi_value * np.pi / 180.0 else: theta = ths_value * np.pi / 180.0 @@ -361,10 +360,11 @@ def process_from_template_ws( print(f"{'*' * 88}\nevent_refl:\n{event_refl}\n{'*' * 88}") # R(Q) - qz, refl, d_refl = event_refl.specular( + qz, refl, d_refl, dq_over_q_bins = event_refl.specular( q_summing=q_summing, tof_weighted=tof_weighted, bck_in_q=bck_in_q, clean=clean, normalize=normalize ) qz_mid = (qz[:-1] + qz[1:]) / 2.0 + dq_over_q = (dq_over_q_bins[:-1] + dq_over_q_bins[1:]) / 2.0 # When using composite direct beam, we don't need a scaling # factor file if the multiplier is in the logs @@ -399,6 +399,7 @@ def process_from_template_ws( qz_mid = qz_mid[template_data.pre_cut : npts - template_data.post_cut] refl = refl[template_data.pre_cut : npts - template_data.post_cut] d_refl = d_refl[template_data.pre_cut : npts - template_data.post_cut] + dq_over_q = dq_over_q[template_data.pre_cut : npts - template_data.post_cut] if normalize and OUTPUT_NORM_DATA: lr = ws_sc.getRun().getProperty("LambdaRequest").value[0] @@ -428,6 +429,6 @@ def process_from_template_ws( meta_data["tof_weighted"] = tof_weighted meta_data["bck_in_q"] = bck_in_q meta_data["theta_offset"] = template_data.angle_offset - return qz_mid, refl, d_refl, meta_data + return qz_mid, refl, d_refl, dq_over_q, meta_data - return qz_mid, refl, d_refl + return qz_mid, refl, d_refl, dq_over_q diff --git a/src/lr_reduction/time_resolved.py b/src/lr_reduction/time_resolved.py index 27702de2..42aeedfd 100644 --- a/src/lr_reduction/time_resolved.py +++ b/src/lr_reduction/time_resolved.py @@ -14,7 +14,7 @@ mantid.kernel.config.setLogLevel(3) from . import template -from .event_reduction import apply_dead_time_correction, compute_resolution +from .event_reduction import apply_dead_time_correction, read_settings def reduce_30Hz_from_ws( @@ -99,7 +99,8 @@ def reduce_30Hz_from_ws( dq0 = 0 if meas_ws_30Hz.getInstrument().hasParameter("dq-constant"): dq0 = meas_ws_30Hz.getInstrument().getNumberParameter("dq-constant")[0] - dq_slope = compute_resolution(meas_ws_30Hz) + # To be backwards compatible with the old normalisation methods keep the compute_resolution from before here + dq_slope = old_compute_resolution(meas_ws_30Hz) print("Resolution: %g + %g Q" % (dq0, dq_slope)) dq = dq0 + dq_slope * q[_idx] return np.asarray([q[_idx], r_q_final[_idx], dr_q_final[_idx], dq]) @@ -362,9 +363,7 @@ def reduce_slices_ws( try: _reduced = template.process_from_template_ws(tmpws, template_data, theta_value=theta_value, ws_db=ws_db) - dq0 = 0 - dq_slope = compute_resolution(tmpws) - dq = dq0 + dq_slope * _reduced[0] + dq = _reduced[0] * _reduced[3] _reduced = [_reduced[0], _reduced[1], _reduced[2], dq] _reduced = np.asarray(_reduced) @@ -386,22 +385,35 @@ def reduce_slices_ws( return reduced -def plot_slices(reduced, title, time_interval, file_path, offset=10, show=True): +def plot_slices(reduced, title, time_interval, file_path, offset=10, show=True, show_dq=True): fig, ax = plt.subplots(figsize=(6, 6)) total_time = 0 _running_offset = 1.0 for _data in reduced: - qz, refl, d_refl, _ = _data - - plt.errorbar( - qz, - refl * _running_offset, - yerr=d_refl * _running_offset, - markersize=4, - marker="o", - label="T=%g s" % total_time, - ) + if show_dq: + qz, refl, d_refl, dq = _data + + plt.errorbar( + qz, + refl * _running_offset, + yerr=d_refl * _running_offset, + xerr=dq, + markersize=4, + marker="o", + label="T=%g s" % total_time, + ) + else: + qz, refl, d_refl, _ = _data + + plt.errorbar( + qz, + refl * _running_offset, + yerr=d_refl * _running_offset, + markersize=4, + marker="o", + label="T=%g s" % total_time, + ) total_time += time_interval _running_offset *= offset @@ -439,3 +451,71 @@ def package_json_data(dynamic_run, dyn_data_dir, out_array=None): json.dump(dict(times=compiled_times, data=compiled_array), fp) return compiled_times, compiled_array + + +def old_compute_resolution(ws, default_dq=0.027, theta=None, q_summing=False): + """ + Compute the Q resolution from the meta data. + Corrected to include both slits. + + Parameters + ---------- + ws : mantid.api.Workspace + Mantid workspace to extract correction meta-data from. + theta : float + Scattering angle in radians + q_summing : bool + If True, the pixel size will be used for the resolution + + Returns + ------- + float + The dQ/Q resolution (FWHM) + """ + settings = read_settings(ws) + + if theta is None: + theta = abs(ws.getRun().getProperty("ths").value[0]) * np.pi / 180.0 + + if q_summing: + # Q resolution is reported as FWHM, so here we consider this to be + # related to the pixel width + sdd = 1830 + if settings.sample_detector_distance: + sdd = settings.sample_detector_distance * 1000 + pixel_size = 0.7 + if settings.pixel_width: + pixel_size = settings.pixel_width + + # All angles here in radians, assuming small angles + dq_over_q = np.arcsin(pixel_size / sdd) / theta + print("Q summing: %g" % dq_over_q) + return dq_over_q + + # We can't compute the resolution if the value of xi is not in the logs. + # Since it was not always logged, check for it here. + if not ws.getRun().hasProperty("BL4B:Mot:xi.RBV"): + # For old data, the resolution can't be computed, so use + # the standard value for the instrument + print("Could not find BL4B:Mot:xi.RBV: using supplied dQ/Q") + return default_dq + + # Xi reference would be the position of xi if the si slit were to be positioned + # at the sample. The distance from the sample to si is then xi_reference - xi. + xi_reference = 445 + if ws.getInstrument().hasParameter("xi-reference"): + xi_reference = ws.getInstrument().getNumberParameter("xi-reference")[0] + + # Distance between the s1 and the sample + s1_sample_distance = 1485 + if settings.s1_sample_distance is not None: + s1_sample_distance = settings.s1_sample_distance * 1000 + + # Get slit gap openings. + s1h = abs(ws.getRun().getProperty("S1VHeight").value[0]) + sih = abs(ws.getRun().getProperty("SiVHeight").value[0]) + xi = abs(ws.getRun().getProperty("BL4B:Mot:xi.RBV").value[0]) + sample_si_distance = xi_reference - xi + slit_distance = s1_sample_distance - sample_si_distance + dq_over_q = (s1h + sih) * 0.5 / slit_distance / theta + return dq_over_q diff --git a/src/lr_reduction/user_defined_function.py b/src/lr_reduction/user_defined_function.py new file mode 100644 index 00000000..7076a982 --- /dev/null +++ b/src/lr_reduction/user_defined_function.py @@ -0,0 +1,99 @@ +import sympy as sp + + +class UserDefinedFunctionError(ValueError): + pass + + +def parse_user_expression(s: str): + """ + Parse function as a string into formula and params. + If entered from a Mantid function should skip the name part. + + Parameters + ---------- + s : str + The user-defined function string. + + Returns + ------- + tuple + (formula, params): + formula : str + The mathematical expression as a string. + params : dict + A dictionary of parameter names and their float values. + + Raises + ------ + ValueError + If the formula is missing in the input string. + """ + parts = [p.strip() for p in s.split(",")] + + formula = None + params = {} + + for part in parts: + key, value = [x.strip() for x in part.split("=", 1)] + + if key.lower() == "formula": + formula = value + elif key.lower() == "name": + continue + else: + params[key] = float(value) + + if formula is None: + raise ValueError("Missing Formula=...") + + return formula, params + + +class UserDefinedFunction: + """Parses and evaluates a user-defined mathematical expression. + + Attributes + ---------- + expr_str : str + The original formula string provided by the user. + + Raises + ------ + SympifyError + If the formula cannot be parsed into a valid sympy expression. + ValueError + If there is a mismatch between parameters used in the formula and those provided. + """ + def __init__(self, definition: str): + self.expr_str, self.params = parse_user_expression(definition) + + self.x = sp.symbols("x") + self.param_symbols = {k: sp.symbols(k) for k in self.params} + + self.expr = sp.sympify( + self.expr_str, + locals={"x": self.x, **self.param_symbols} + ) + + # Validate that all symbols in the expression are accounted for in the parameters + expr_params = self.expr.free_symbols - {self.x} + defined_params = set(self.param_symbols.values()) + + if expr_params != defined_params: + missing = expr_params - defined_params + extra = defined_params - expr_params + raise UserDefinedFunctionError( + "Parameter mismatch in user-defined function. " + f"Missing parameters: {[str(p) for p in missing]}. " + f"Extra parameters: {[str(p) for p in extra]}." + ) + + self._f = sp.lambdify( + (self.x, *self.param_symbols.values()), + self.expr, + modules="numpy" + ) + + def __call__(self, x): + return self._f(x, *self.params.values()) diff --git a/src/lr_reduction/workflow.py b/src/lr_reduction/workflow.py index 7b7461c0..1a735e68 100644 --- a/src/lr_reduction/workflow.py +++ b/src/lr_reduction/workflow.py @@ -75,13 +75,14 @@ def reduce( template_data.angle_offset = theta_offset # Call the reduction using the template - qz_mid, refl, d_refl, meta_data = template.process_from_template_ws( + qz_mid, refl, d_refl, dq_over_q, meta_data = template.process_from_template_ws( ws, template_data, q_summing=q_summing, tof_weighted=bck_in_q, clean=q_summing, bck_in_q=bck_in_q, info=True ) # Save partial results coll = output.RunCollection() - coll.add(qz_mid, refl, d_refl, meta_data=meta_data) + dq_calc = dq_over_q * qz_mid + coll.add(qz_mid, refl, d_refl, dq=dq_calc, meta_data=meta_data) # If this is live data, put it in a separate file to avoid conflict with auto-reduction if is_live: @@ -419,9 +420,11 @@ def reduce_explorer(ws, ws_db, theta_pv=None, center_pixel=145, db_center_pixel= ) # R(Q) - qz, refl, d_refl = event_refl.specular( + qz, refl, d_refl, dq_over_q_bins = event_refl.specular( q_summing=None, tof_weighted=False, bck_in_q=False, clean=False, normalize=True ) qz_mid = (qz[:-1] + qz[1:]) / 2.0 + dq_over_q = (dq_over_q_bins[:-1] + dq_over_q_bins[1:]) / 2.0 + dq_output = dq_over_q * qz_mid - return qz_mid, refl, d_refl + return qz_mid, refl, d_refl, dq_output diff --git a/tests/test_dead_time.py b/tests/test_dead_time.py index 540612f4..1c6a9727 100644 --- a/tests/test_dead_time.py +++ b/tests/test_dead_time.py @@ -92,10 +92,10 @@ def test_full_reduction(nexus_dir, template_dir): template_data = template.read_template(template_path, sequence_number) template_data.dead_time = True - _, r1, _ = template.process_from_template_ws(ws, template_data) + _, r1, _, _ = template.process_from_template_ws(ws, template_data) template_data.dead_time = False - _, r2, _ = template.process_from_template_ws(ws, template_data) + _, r2, _, _ = template.process_from_template_ws(ws, template_data) corr = r1 / r2 for c in corr: diff --git a/tests/test_reduction.py b/tests/test_reduction.py index 1fa0a40f..9919c148 100644 --- a/tests/test_reduction.py +++ b/tests/test_reduction.py @@ -58,16 +58,20 @@ def test_q_summing(template_dir, nexus_dir): template.read_template(template_path, 7) with amend_config(data_dir=nexus_dir): ws_sc = mtd_api.Load("REF_L_%s" % 198415) - qz_mid0, refl0, _, meta_data = template.process_from_template_ws(ws_sc, template_path, info=True) + qz_mid0, refl0, _, dq_over_q, _ = template.process_from_template_ws(ws_sc, template_path, info=True) - assert np.fabs(meta_data["dq_over_q"] - 0.02261) < 1e-3 + # TODO: tighten the tolerance here once the equation has been updated + dq_over_q_expected = [0.014] * np.ones(43) + np.testing.assert_array_almost_equal(dq_over_q, dq_over_q_expected, decimal=3) # Now try with Q summing, which should have similar results - qz_mid, refl, _, meta_data = template.process_from_template_ws( + qz_mid, refl, _, dq_over_q, _ = template.process_from_template_ws( ws_sc, template_path, tof_weighted=True, info=True, q_summing=True ) - assert np.fabs(meta_data["dq_over_q"] - 0.009354) < 1e-5 + # TODO: tighten the tolerance here once the equation has been updated + dq_over_q_expected = [0.017] * np.ones(44) + np.testing.assert_array_almost_equal(dq_over_q, dq_over_q_expected, decimal=3) # Note that TOF weighted may have a slightly different range, so here we skip # the extra point. @@ -109,9 +113,9 @@ def test_q_summing_as_option(template_dir, nexus_dir, template_file, q_summing, ws_sc = mtd_api.Load("REF_L_%s" % 198415) with patch.object(event_reduction.EventReflectivity, "specular") as mock_specular: - mock_specular.return_value = (np.array([1, 2, 3]), np.array([0.1, 0.2]), np.array([0.01, 0.02])) + mock_specular.return_value = (np.array([1, 2, 3]), np.array([0.1, 0.2]), np.array([0.01, 0.02]), np.array([0.01, 0.02])) - qz_mid, refl, _, meta_data = template.process_from_template_ws( + qz_mid, refl, _, dq_over_q, meta_data = template.process_from_template_ws( ws_sc, template_path, tof_weighted=tof_weighted, info=True, q_summing=q_summing ) @@ -131,17 +135,18 @@ def test_full_reduction(template_dir, nexus_dir): qz_all = [] refl_all = [] d_refl_all = [] + dq_q_all = [] first_run = None for run_number in range(198409, 198417): with amend_config(data_dir=nexus_dir): ws_sc = mtd_api.Load("REF_L_%s" % run_number) - qz_mid, refl, d_refl = template.process_from_template_ws(ws_sc, template_path) + qz_mid, refl, d_refl, dq_over_q = template.process_from_template_ws(ws_sc, template_path) if first_run is None: first_run = run_number - resolution = event_reduction.compute_resolution(ws_sc) for i in range(len(qz_mid)): + dq_q_all.append(dq_over_q[i]) qz_all.append(qz_mid[i]) refl_all.append(refl[i]) d_refl_all.append(d_refl[i]) @@ -149,13 +154,18 @@ def test_full_reduction(template_dir, nexus_dir): qz_all = np.asarray(qz_all) refl_all = np.asarray(refl_all) d_refl_all = np.asarray(d_refl_all) + dq_q_all = np.asarray(dq_q_all) idx = np.argsort(qz_all) qz_all = np.take_along_axis(qz_all, idx, axis=None) refl_all = np.take_along_axis(refl_all, idx, axis=None) d_refl_all = np.take_along_axis(d_refl_all, idx, axis=None) + dq_q_all = np.take_along_axis(dq_q_all, idx, axis=None) - assert np.fabs(resolution - 0.022751) < 1e-5 + # TODO: tighten the tolerance and compare to the values in the reference file once the equation has been updated + dq_q_expected = [0.01] * np.ones(241) + np.testing.assert_array_almost_equal(dq_q_all, dq_q_expected, decimal=2) + # assert np.fabs(dq_q_all[0] - 0.022751) < 1e-5 ref_data = np.loadtxt("data/reference_rq.txt").T # Optional plotting for checking tests: @@ -263,17 +273,6 @@ def test_reduce_functional_bck(nexus_dir, template_dir, tmp_path): assert average_fractional_difference < 0.07 -def test_compute_wavelength_resolution_n_spectra(): - """ - Call compute wavelength resolution method with a workspace - of multiple spectra - """ - ws = mtd_api.CreateSampleWorkspace(WorkspaceType="Event") - - with pytest.raises(ValueError): - _, _ = event_reduction.compute_wavelength_resolution(ws) - - def test_reduce_bck_option_mismatch(template_dir, nexus_dir, tmp_path): """ Ask for functional background but pass by a background range with diff --git a/tests/unit/lr_reduction/test_data_info.py b/tests/unit/lr_reduction/test_data_info.py index a9f8edac..af5ad9fe 100644 --- a/tests/unit/lr_reduction/test_data_info.py +++ b/tests/unit/lr_reduction/test_data_info.py @@ -1,85 +1,127 @@ -from unittest.mock import Mock, patch - -from lr_reduction.data_info import DataType - - -@patch("lr_reduction.data_info.SampleLogValues") -def test_from_workspace_direct_beam_earth_centered_coordinates(mock_sample_logs_class): - """Test direct beam detection with earth-centered coordinates""" - mock_logs = { - "BL4B:CS:Mode:Coordinates": 0, - "thi": 0.800, - "tthd": 0.805, - } - mock_sample_logs_class.return_value = mock_logs - - result = DataType.from_workspace(Mock()) - assert result == DataType.DIRECT_BEAM - - -@patch("lr_reduction.data_info.SampleLogValues") -def test_from_workspace_direct_beam_free_liquid_mode(mock_sample_logs_class): - """Test direct beam detection with free liquid mode""" - mock_logs = { - "BL4B:CS:Mode:Coordinates": 1, - "BL4B:CS:ExpPl:OperatingMode": "Free Liquid", - "thi": 0.210, - "tthd": 0.212, - } - mock_sample_logs_class.return_value = mock_logs - - result = DataType.from_workspace(Mock()) - assert result == DataType.DIRECT_BEAM - - -@patch("lr_reduction.data_info.SampleLogValues") -def test_from_workspace_reflected_beam_earth_centered(mock_sample_logs_class): - """Test reflected beam detection with earth-centered coordinates""" - mock_logs = { - "BL4B:CS:Mode:Coordinates": 0, - "thi": 0.5, - "tthd": 1.0, - } - mock_sample_logs_class.return_value = mock_logs - - result = DataType.from_workspace(Mock()) - assert result == DataType.REFLECTED_BEAM - - -@patch("lr_reduction.data_info.SampleLogValues") -def test_from_workspace_reflected_beam_beam_centered(mock_sample_logs_class): - """Test reflected beam detection with beam-centered coordinates""" - mock_logs = { - "BL4B:CS:Mode:Coordinates": 1, - "BL4B:CS:ExpPl:OperatingMode": "Other", - "ths": 0.5, - "tthd": 1.0, - } - mock_sample_logs_class.return_value = mock_logs - - result = DataType.from_workspace(Mock()) - assert result == DataType.REFLECTED_BEAM - - -@patch("lr_reduction.data_info.SampleLogValues") -def test_from_workspace_direct_beam_beam_centered(mock_sample_logs_class): - """Test direct beam detection with beam-centered coordinates""" - mock_logs = { - "BL4B:CS:Mode:Coordinates": 1, - "BL4B:CS:ExpPl:OperatingMode": "Other", - "ths": 0.0006, - "tthd": 0.0008, - } - mock_sample_logs_class.return_value = mock_logs - - result = DataType.from_workspace(Mock()) - assert result == DataType.DIRECT_BEAM - - -@patch("lr_reduction.data_info.SampleLogValues") -def test_from_workspace_missing_logs(mock_sample_logs_class): - """Test that missing logs default to reflected beam""" - mock_sample_logs_class.return_value = {} - - result = DataType.from_workspace(Mock()) - assert result == DataType.REFLECTED_BEAM +import pytest +from mantid.simpleapi import AddSampleLog, CreateSingleValuedWorkspace, mtd + +from lr_reduction.data_info import CoordinateSystem, DataType + + +class TestDataType: + """Test suite for DataType enum""" + + def test_from_workspace_direct_beam_earth_centered_coordinates(self): + """Test direct beam detection with earth-centered coordinates""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:Mode:Coordinates", LogText="0", LogType="Number Series") + AddSampleLog(Workspace=workspace, LogName="thi", LogText="0.800", LogType="Number") + AddSampleLog(Workspace=workspace, LogName="tthd", LogText="0.805", LogType="Number") + + result = DataType.from_workspace(workspace) + assert result == DataType.DIRECT_BEAM + + + def test_from_workspace_direct_beam_free_liquid_mode(self): + """Test direct beam detection with free liquid mode""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:ExpPl:OperatingMode", LogText="Free Liquid", LogType="String") + AddSampleLog(Workspace=workspace, LogName="thi", LogText="0.210", LogType="Number") + AddSampleLog(Workspace=workspace, LogName="tthd", LogText="0.212", LogType="Number") + + result = DataType.from_workspace(workspace) + assert result == DataType.DIRECT_BEAM + + + def test_from_workspace_reflected_beam_earth_centered(self): + """Test reflected beam detection with earth-centered coordinates""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:Mode:Coordinates", LogText="0", LogType="Number Series") + AddSampleLog(Workspace=workspace, LogName="thi", LogText="0.5", LogType="Number") + AddSampleLog(Workspace=workspace, LogName="tthd", LogText="1.0", LogType="Number") + + result = DataType.from_workspace(workspace) + assert result == DataType.REFLECTED_BEAM + + + def test_from_workspace_reflected_beam_beam_centered(self): + """Test reflected beam detection with beam-centered coordinates""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:Mode:Coordinates", LogText="1", LogType="Number Series") + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:ExpPl:OperatingMode", LogText="Other", LogType="String") + AddSampleLog(Workspace=workspace, LogName="thi", LogText="0.5", LogType="Number") + AddSampleLog(Workspace=workspace, LogName="tthd", LogText="1.0", LogType="Number") + + result = DataType.from_workspace(workspace) + assert result == DataType.REFLECTED_BEAM + + + def test_from_workspace_direct_beam_beam_centered(self): + """Test direct beam detection with beam-centered coordinates""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:Mode:Coordinates", LogText="1", LogType="Number Series") + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:ExpPl:OperatingMode", LogText="Other", LogType="String") + AddSampleLog(Workspace=workspace, LogName="ths", LogText="0.0006", LogType="Number") + AddSampleLog(Workspace=workspace, LogName="tthd", LogText="0.0008", LogType="Number") + + result = DataType.from_workspace(workspace) + assert result == DataType.DIRECT_BEAM + + + def test_from_workspace_missing_logs(self): + """Test that missing logs default to reflected beam""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + + result = DataType.from_workspace(workspace) + assert result == DataType.REFLECTED_BEAM + + +class TestCoordinateSystem: + """Test suite for CoordinateSystem enum""" + + @pytest.mark.parametrize("log_coordinates,expected_coordinate_system", [ + ("0", CoordinateSystem.EARTH_CENTERED), + ("1", CoordinateSystem.BEAM_CENTERED), + ]) + def test_from_workspace_coordinates_only(self, log_coordinates, expected_coordinate_system): + """Test coordinate system detection via coordinates log only""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:Mode:Coordinates", LogText=log_coordinates, LogType="Number Series") + + result = CoordinateSystem.from_workspace(workspace) + assert result == expected_coordinate_system + + @pytest.mark.parametrize("log_operatingmode,expected_coordinate_system", [ + ("Free Liquid", CoordinateSystem.EARTH_CENTERED), + ("Other", CoordinateSystem.BEAM_CENTERED), + ]) + def test_from_workspace_operatingmode_only(self, log_operatingmode, expected_coordinate_system): + """Test coordinate system detection via operating mode log only""" + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:ExpPl:OperatingMode", LogText=log_operatingmode, LogType="String") + + result = CoordinateSystem.from_workspace(workspace) + assert result == expected_coordinate_system + + @pytest.mark.parametrize("log_coordinates,log_operatingmode,expected_coordinate_system", [ + ("0", "Other", CoordinateSystem.EARTH_CENTERED), + ("0", "Free Liquid", CoordinateSystem.EARTH_CENTERED), + ("1", "Other", CoordinateSystem.BEAM_CENTERED), + ("1", "Free Liquid", CoordinateSystem.BEAM_CENTERED), + ]) + def test_from_workspace_both_logs_present(self, log_coordinates, log_operatingmode, expected_coordinate_system): + """Test coordinate system detection when both logs are present + + Note: the coordinates log takes precedence over operating mode. + """ + workspace = mtd.unique_hidden_name() + CreateSingleValuedWorkspace(OutputWorkspace=workspace) + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:Mode:Coordinates", LogText=log_coordinates, LogType="Number Series") + AddSampleLog(Workspace=workspace, LogName="BL4B:CS:ExpPl:OperatingMode", LogText=log_operatingmode, LogType="String") + + result = CoordinateSystem.from_workspace(workspace) + assert result == expected_coordinate_system diff --git a/tests/unit/test_event_reduction.py b/tests/unit/lr_reduction/test_event_reduction.py similarity index 56% rename from tests/unit/test_event_reduction.py rename to tests/unit/lr_reduction/test_event_reduction.py index 5b32d423..b226f070 100644 --- a/tests/unit/test_event_reduction.py +++ b/tests/unit/lr_reduction/test_event_reduction.py @@ -1,9 +1,11 @@ from unittest.mock import MagicMock +import mantid.simpleapi as mtd_api import numpy as np import pytest from lr_reduction import event_reduction +from lr_reduction.utils import amend_config @pytest.fixture @@ -18,7 +20,8 @@ def _make_mock_ws(properties=None, xi_reference=445, start_time="2025-07-14T10:0 def get_property_side_effect(name): val = properties.get(name) if val is None: - raise KeyError(f"Property {name} not in mock properties") + # Mantid raises RuntimeError if property not found for workspace run + raise RuntimeError(f"Property {name} not in mock properties") mock = MagicMock() mock.value = [val] # keep consistent with .value[0] return mock @@ -75,3 +78,33 @@ def test_trapezoid_gaussian_function(make_mock_ws): assert dth_over_th == pytest.approx(0.01176, rel=1e-3) assert L_bottom == pytest.approx(0.0093, rel=1e-3) assert l_top == pytest.approx(0.0031, rel=1e-3) + + +@pytest.mark.datarepo +@pytest.mark.parametrize("q_summing, theta_expected, dtheta_expected", [(False, 1.1825526, 0.011999676), (True, 1.1825526, 0.031941999)]) +def test_compute_theta_resolution(q_summing, theta_expected, dtheta_expected, nexus_dir): + """Test the compute_theta_resolution function.""" + with amend_config(data_dir=nexus_dir): + ws = mtd_api.LoadEventNexus("REF_L_201287") + + theta, dtheta = event_reduction.compute_theta_resolution(ws, q_summing=q_summing) + assert theta == pytest.approx(theta_expected, rel=1e-6) + assert dtheta == pytest.approx(dtheta_expected, rel=1e-6) + + +def test_compute_wavelength_resolution(): + """Test the compute_wavelength_resolution function.""" + resolution_function_str = "name=UserFunction, Formula=L - A * exp(-k * x), L=0.07564423, A=0.13093263, k=0.34918918" + + wavelengths = np.array([11.4254409079602, 11.20141265486294, 10.981777112610725, 10.766448149618357, 10.555341323155254, 10.34837384623064, 10.145464555128079, 9.946533877576549, 9.751503801545635, 9.560297844652583, 9.3728410241692, 9.189059827616862, 9.0088821839381, 8.83223743523343, 8.659056309052383, 8.489270891227827, 8.322814599242967, 8.159622156120555, 7.999629564824074, 7.842774083160856, 7.688994199177309]) + + # Calculate expected resolution using the default formula: + # L - A * exp(-k * x), L=0.07564423, A=0.13093263, k=0.34918918 + A = 0.13093263 + L = 0.07564423 + k = 0.34918918 + expected_resolution = L - A * np.exp(-k * wavelengths) + + _, wavelength_resolution = event_reduction.compute_wavelength_resolution(wavelengths, resolution_function_str) + assert len(wavelength_resolution) == len(wavelengths) + np.testing.assert_array_almost_equal(wavelength_resolution, expected_resolution, decimal=5) diff --git a/tests/unit/lr_reduction/test_user_defined_function.py b/tests/unit/lr_reduction/test_user_defined_function.py new file mode 100644 index 00000000..bc083fec --- /dev/null +++ b/tests/unit/lr_reduction/test_user_defined_function.py @@ -0,0 +1,95 @@ +import numpy as np +import pytest +import sympy + +from lr_reduction.user_defined_function import UserDefinedFunction, UserDefinedFunctionError, parse_user_expression + + +class TestParseUserExpression: + """Tests for parse_user_expression function.""" + + def test_parse_simple_formula(self): + """Test parsing a simple formula with no parameters.""" + formula, params = parse_user_expression("formula=x+1") + assert formula == "x+1" + assert params == {} + + def test_parse_formula_with_parameters(self): + """Test parsing formula with multiple parameters.""" + formula, params = parse_user_expression("formula=a*x+b, a=2.5, b=1.0") + assert formula == "a*x+b" + assert params == {"a": 2.5, "b": 1.0} + + def test_parse_with_name_field(self): + """Test that name field is skipped.""" + formula, params = parse_user_expression("name=MyFunc, formula=x**2, c=3.0") + assert formula == "x**2" + assert params == {"c": 3.0} + + def test_parse_with_whitespace(self): + """Test parsing with extra whitespace.""" + formula, params = parse_user_expression(" formula = x*2 , param = 5.5 ") + assert formula == "x*2" + assert params == {"param": 5.5} + + def test_parse_missing_formula_raises_error(self): + """Test that missing formula raises ValueError.""" + with pytest.raises(ValueError, match="Missing Formula"): + parse_user_expression("a=1.0, b=2.0") + + def test_parse_empty_parameters(self): + """Test parsing formula with no parameters.""" + formula, params = parse_user_expression("formula=sin(x)") + assert formula == "sin(x)" + assert params == {} + + +class TestUserDefinedFunction: + """Tests for UserDefinedFunction class.""" + + def test_simple_linear_function(self): + """Test evaluation of a simple linear function.""" + udf = UserDefinedFunction("formula=2*x+1") + result = udf(3) + assert result == 7 + + def test_function_with_parameters(self): + """Test function with parameters.""" + udf = UserDefinedFunction("formula=a*x+b, a=2.0, b=3.0") + result = udf(5) + np.testing.assert_almost_equal(result, 13.0) + + def test_function_with_numpy_array(self): + """Test function evaluation with numpy array input.""" + udf = UserDefinedFunction("formula=x**2") + x = np.array([1, 2, 3, 4]) + result = udf(x) + np.testing.assert_array_equal(result, np.array([1, 4, 9, 16])) + + def test_function_with_multiple_parameters(self): + """Test function with multiple parameters.""" + udf = UserDefinedFunction("formula=a*x**2+b*x+c, a=1.0, b=2.0, c=3.0") + result = udf(2) + np.testing.assert_almost_equal(result, 11.0) + + def test_function_with_trigonometric_expression(self): + """Test function with trigonometric expressions.""" + udf = UserDefinedFunction("formula=sin(x)") + result = udf(0) + np.testing.assert_almost_equal(result, 0.0) + + def test_function_with_exponential(self): + """Test function with exponential expression.""" + udf = UserDefinedFunction("formula=exp(scale*x), scale=1.0") + result = udf(0) + np.testing.assert_almost_equal(result, 1.0) + + def test_invalid_formula_raises_error(self): + """Test that invalid formula raises an error.""" + with pytest.raises(sympy.SympifyError): + UserDefinedFunction("formula=x+++") + + def test_parameter_name_mismatch_raises_error(self): + """Test that parameter names in formula must match those provided.""" + with pytest.raises(UserDefinedFunctionError, match="Parameter mismatch"): + UserDefinedFunction("formula=a*x+b, a=2.0, c=3.0")