diff --git a/.github/workflows/rtd-preview.yml b/.github/workflows/rtd-preview.yml new file mode 100644 index 0000000..dc2cf7b --- /dev/null +++ b/.github/workflows/rtd-preview.yml @@ -0,0 +1,30 @@ +name: Read the Docs PR preview + +on: + pull_request_target: + types: + - opened + - synchronize + - reopened + # Only fire when something that could change the docs build is touched. + paths: + - "docs/**" + - ".readthedocs.yaml" + - "conda_envs/environment-docs.yml" + - "examples/**" + - "pytensor_ml/**" + - "pyproject.toml" + +permissions: + pull-requests: write + +jobs: + documentation-links: + runs-on: ubuntu-latest + steps: + - uses: readthedocs/actions/preview@v1 + with: + # Project slug as configured on Read the Docs. Verify this matches the slug shown in the + # RTD project URL (https://readthedocs.org/projects//) once the project is imported + # there. + project-slug: "pytensor-ml" diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..6af33a9 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,24 @@ +version: 2 + +sphinx: + configuration: docs/source/conf.py + fail_on_warning: false + +conda: + environment: conda_envs/environment-docs.yml + +python: + install: + - method: pip + path: . + +build: + os: "ubuntu-22.04" + tools: + python: "miniforge3-latest" + jobs: + # hatch-vcs derives the version from git tags; RTD's default checkout is shallow and tagless, so + # fetch tags or pytensor_ml.__version__ falls back to 0.0.0+unknown and the version selector + # labels break. + post_checkout: + - git fetch --tags --unshallow || true diff --git a/README.md b/README.md index c157c69..4770933 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,96 @@ # pytensor_ml -Neural network package built on Pytensor + +A(nother) deep learning library, built on top of [PyTensor](https://github.com/pymc-devs/pytensor). + +Networks are ordinary PyTensor graphs. You build one out of layers, and everything PyTensor already does — +symbolic differentiation, graph rewrites, and compilation to Numba, C, JAX, PyTorch, or MLX — applies to it +unchanged. Training is a compiled function that takes a batch and returns a loss; there is no separate runtime +or tape. + +That goes all the way down: layers are graph constructors, parameters are shared variables, and a training +step is a compiled function whose updates are the optimizer. Because a model is only a graph, it composes with +any other PyTensor graph — a PyMC model included — as there is nothing else to interoperate with. + +> **Status: pre-alpha.** The API is still moving, and there is no release-to-release compatibility guarantee yet. + +## Installation + +```bash +pip install pytensor-ml +``` + +The only hard dependencies are `pytensor`, `numpy`, and `safetensors`. A backend beyond the default (`numba`, +`jax`, `torch`, `mlx`) is installed separately, and only loads when you actually compile against it. + +## Quickstart + +Train a classifier on scikit-learn's digits, then run inference: + +```python +import numpy as np +import pytensor + +pytensor.config.floatX = "float32" + +from sklearn.datasets import load_digits + +from pytensor_ml.activations import ReLU +from pytensor_ml.layers import Input, Linear, Sequential +from pytensor_ml.loss import CrossEntropy +from pytensor_ml.model import Model +from pytensor_ml.optim import adam, chain, clip_by_global_norm, cosine_schedule +from pytensor_ml.util import DataLoader + +X, y = load_digits(return_X_y=True) +X = (X / 16.0).astype("float32") +y_onehot = np.eye(10, dtype="float32")[y] + +X_in = Input("X_in", shape=(None, 64)) +network = Sequential( + Linear("fc1", n_in=64, n_out=128), + ReLU(), + Linear("logits", n_in=128, n_out=10), +) +model = Model(X_in, network(X_in)).initialize(seed=0) + +rule = chain(adam(learning_rate=cosine_schedule(1e-3, total_steps=500)), clip_by_global_norm(1.0)) +loss_fn = CrossEntropy(expect_onehot_labels=True, expect_logits=True, reduction="mean") +step = model.compile_train(rule, loss_fn, ndim_out=2) + +loader = DataLoader(X, y_onehot, batch_size=64, random_state=0) +for _ in range(500): + loss_value = step(*loader()) + +accuracy = (model.predict(X).argmax(axis=-1) == y).mean() +``` + +`compile_train` builds the loss against a target placeholder, differentiates it, folds in any stateful layer +updates (batch norm running statistics, RNG advances, the training clock a schedule reads), and compiles a +one-step function. `predict` compiles a separate inference pass, with dropout removed and batch norm reading +its running statistics. + +## Documentation + +The full API reference and user guide live at +[pytensor-ml.readthedocs.io](https://pytensor-ml.readthedocs.io). + +For worked models end to end — training loops, convolutional and recurrent networks, transformers, saving and +reloading — see the [examples gallery](https://pytensor-ml.readthedocs.io/en/latest/examples/gallery.html). + +## Contributing + +Contributions are welcome. To get set up: + +```bash +pip install -e ".[dev]" +pre-commit install +pytest +``` + +Formatting and linting run through `ruff` under pre-commit, and `mypy` checks `pytensor_ml/`; both also run in +CI. Bug reports and feature requests belong in the +[issue tracker](https://github.com/pymc-devs/pytensor-ml/issues). + +## License + +Apache 2.0. See [LICENSE](LICENSE). diff --git a/conda_envs/environment-docs.yml b/conda_envs/environment-docs.yml new file mode 100644 index 0000000..e550874 --- /dev/null +++ b/conda_envs/environment-docs.yml @@ -0,0 +1,35 @@ +# The environment Read the Docs builds from. `pixi run docs-build` uses the equivalent list under +# [tool.pixi.feature.docs] in pyproject.toml; the two have to move together. +name: pytensor_ml-docs +channels: + - conda-forge + - nodefaults + +dependencies: + - python>=3.12 + # Runtime deps: autodoc imports pytensor_ml, so the full runtime stack has to be in scope. + - pytensor>=3.3.0,<3.4.0 + - numpy + - safetensors + # The gallery extension renders notebook thumbnails with matplotlib. + - matplotlib + + # Docs build deps. + - ipython + - jupyter + - sphinx>=7 + - pydata-sphinx-theme + - myst-nb + - numpydoc + - sphinx-copybutton + - sphinx-design + - sphinx-codeautolink + - sphinx-sitemap + - sphinx-notfound-page + - sphinx-autobuild + - jupyter-sphinx + - sphinxcontrib-bibtex + - pip + - pip: + # pytensor_ml itself so autodoc resolves the current source tree. + - -e .. diff --git a/conda_envs/pytensor_ml.yml b/conda_envs/pytensor_ml.yml index 2152ac1..fba4723 100644 --- a/conda_envs/pytensor_ml.yml +++ b/conda_envs/pytensor_ml.yml @@ -20,13 +20,6 @@ dependencies: - pytest-mock - pyyaml # tests/test_workflow_groups.py reads the CI matrix - # For building docs - - sphinx - - sphinx_rtd_theme - - pygments - - pydot - - ipython - # developer tools - pre-commit # Pinned rather than floated: a local run that disagrees with CI about the version is a local run diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..f72e953 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,16 @@ +# Sphinx build output +build/ +jupyter_execute/ + +# Python cache +__pycache__/ +*.pyc + +# Autosummary-generated stubs (one .rst per object, regenerated on build) +source/api/generated/ +source/api/**/generated/ +source/api/**/classmethods/ + +# Notebook gallery artifacts written by docs/sphinxext/generate_gallery.py +source/examples/ +source/_thumbnails/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..09c0c53 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,34 @@ +# Minimal Makefile for Sphinx documentation. +# Mirrors the standard sphinx-quickstart output. + +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +.PHONY: help clean html show livehtml linkcheck Makefile + +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +clean: + rm -rf "$(BUILDDIR)" + rm -rf "$(SOURCEDIR)"/api/generated + rm -rf "$(SOURCEDIR)"/api/*/generated + rm -rf "$(SOURCEDIR)"/_thumbnails + rm -f "$(SOURCEDIR)"/examples/gallery.rst + +html: + @$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +show: html + @open "$(BUILDDIR)/html/index.html" + +livehtml: + sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS) $(O) + +linkcheck: + @$(SPHINXBUILD) -M linkcheck "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..49fa0ba --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,29 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Install Sphinx, then re-run. + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/.gitkeep b/docs/source/_static/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/source/_templates/autosummary/class.rst b/docs/source/_templates/autosummary/class.rst new file mode 100644 index 0000000..f1f165f --- /dev/null +++ b/docs/source/_templates/autosummary/class.rst @@ -0,0 +1,34 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + + {% block methods %} + {% if methods %} + + .. rubric:: Methods + + .. autosummary:: + :toctree: classmethods + + {% for item in methods %} + {%- if item not in inherited_members %} + {{ objname }}.{{ item }} + {% endif %} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: Attributes + + .. autosummary:: + {% for item in attributes %} + {%- if item not in inherited_members %} + ~{{ name }}.{{ item }} + {% endif %} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..c700208 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,18 @@ +.. _api: + +API Reference +============= + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + api/model + api/layers + api/activations + api/loss + api/optim + api/state + api/serialization + api/pytensorf + api/util diff --git a/docs/source/api/activations.rst b/docs/source/api/activations.rst new file mode 100644 index 0000000..98b27d8 --- /dev/null +++ b/docs/source/api/activations.rst @@ -0,0 +1,17 @@ +Activations +=========== + +.. currentmodule:: pytensor_ml.activations + +.. autosummary:: + :toctree: generated/ + + Activation + ReLU + LeakyReLU + GELU + Swish + Sigmoid + SoftPlus + Softmax + Tanh diff --git a/docs/source/api/layers.rst b/docs/source/api/layers.rst new file mode 100644 index 0000000..2b335ac --- /dev/null +++ b/docs/source/api/layers.rst @@ -0,0 +1,101 @@ +Layers +====== + +.. currentmodule:: pytensor_ml.layers + +Base +---- + +.. autosummary:: + :toctree: generated/ + + Layer + +Combinators +----------- + +.. autosummary:: + :toctree: generated/ + + Input + Sequential + Concatenate + Flatten + Squeeze + +Dense +----- + +.. autosummary:: + :toctree: generated/ + + Linear + Embedding + +Convolution and pooling +----------------------- + +.. autosummary:: + :toctree: generated/ + + Conv1D + Conv2D + ConvTranspose1D + ConvTranspose2D + MaxPool1D + MaxPool2D + AvgPool1D + AvgPool2D + +Padding +------- + +.. autosummary:: + :toctree: generated/ + + ZeroPad1D + ZeroPad2D + ConstantPad1D + ConstantPad2D + ReflectionPad1D + ReflectionPad2D + ReplicationPad1D + ReplicationPad2D + +Normalization and regularization +-------------------------------- + +.. autosummary:: + :toctree: generated/ + + BatchNorm + LayerNorm + Dropout + +Recurrent +--------- + +.. autosummary:: + :toctree: generated/ + + RNN + LSTM + GRU + Bidirectional + Recurrent + RecurrentCell + ElmanCell + LSTMCell + GRUCell + +Attention and transformers +-------------------------- + +.. autosummary:: + :toctree: generated/ + + MultiheadAttention + CausalSelfAttention + FeedForward + TransformerBlock + scaled_dot_product_attention diff --git a/docs/source/api/loss.rst b/docs/source/api/loss.rst new file mode 100644 index 0000000..6c38855 --- /dev/null +++ b/docs/source/api/loss.rst @@ -0,0 +1,12 @@ +Losses +====== + +.. currentmodule:: pytensor_ml.loss + +.. autosummary:: + :toctree: generated/ + + Loss + SquaredError + CrossEntropy + supervised_loss diff --git a/docs/source/api/model.rst b/docs/source/api/model.rst new file mode 100644 index 0000000..8ecce4b --- /dev/null +++ b/docs/source/api/model.rst @@ -0,0 +1,9 @@ +Model +===== + +.. currentmodule:: pytensor_ml.model + +.. autosummary:: + :toctree: generated/ + + Model diff --git a/docs/source/api/optim.rst b/docs/source/api/optim.rst new file mode 100644 index 0000000..ab4fc56 --- /dev/null +++ b/docs/source/api/optim.rst @@ -0,0 +1,115 @@ +Optimization +============ + +.. currentmodule:: pytensor_ml.optim + +Training +-------- + +.. autosummary:: + :toctree: generated/ + + compile_train + +Update rules +------------ + +.. autosummary:: + :toctree: generated/ + + sgd + adam + adamw + nadam + adamax + rmsprop + rprop + adagrad + adadelta + +Transforms +---------- + +.. autosummary:: + :toctree: generated/ + + chain + scale + scale_by_schedule + add_weight_decay + trace + clip_by_global_norm + clip_by_value + +Guards and policies +------------------- + +.. autosummary:: + :toctree: generated/ + + skip_if + apply_if_finite + nonfinite + large_step + reduce_on_plateau + SkipCondition + +Schedules +--------- + +.. autosummary:: + :toctree: generated/ + + constant_schedule + linear_schedule + cosine_schedule + exponential_schedule + polynomial_schedule + step_decay + join_schedules + +Building blocks +--------------- + +.. autosummary:: + :toctree: generated/ + + get_gradients + scalar_state + to_floatx + +.. currentmodule:: pytensor_ml.optim.base + +.. autosummary:: + :toctree: generated/ + + UpdateRule + Transform + Schedule + Rate + LearningRate + +.. currentmodule:: pytensor_ml.optim.guards + +.. autosummary:: + :toctree: generated/ + + Decision + +.. currentmodule:: pytensor_ml.optim + +Low-level update functions +-------------------------- + +.. autosummary:: + :toctree: generated/ + + sgd_updates + adam_updates + adamw_updates + nadam_updates + adamax_updates + rmsprop_updates + rprop_updates + adagrad_updates + adadelta_updates diff --git a/docs/source/api/pytensorf.rst b/docs/source/api/pytensorf.rst new file mode 100644 index 0000000..c91614f --- /dev/null +++ b/docs/source/api/pytensorf.rst @@ -0,0 +1,33 @@ +Graph tools +=========== + +.. currentmodule:: pytensor_ml.pytensorf + +Compilation +----------- + +.. autosummary:: + :toctree: generated/ + + function + compile_predict + rewrite_for_prediction + rewrite_pregrad + +Graph inspection +---------------- + +.. autosummary:: + :toctree: generated/ + + collect_graph_inputs + collect_data_inputs + collect_trainable_params + collect_non_trainable_params + collect_differentiable_params + collect_shared_variables + collect_step_counters + collect_clock_updates + collect_non_trainable_updates + find_rng_nodes + as_output_list diff --git a/docs/source/api/serialization.rst b/docs/source/api/serialization.rst new file mode 100644 index 0000000..3dd8ef3 --- /dev/null +++ b/docs/source/api/serialization.rst @@ -0,0 +1,24 @@ +Saving and loading +================== + +.. currentmodule:: pytensor_ml + +Networks +-------- + +.. autosummary:: + :toctree: generated/ + + save_pretrained + from_pretrained + save_network + load_network + +Weights +------- + +.. autosummary:: + :toctree: generated/ + + save_state + load_state diff --git a/docs/source/api/state.rst b/docs/source/api/state.rst new file mode 100644 index 0000000..97b63b5 --- /dev/null +++ b/docs/source/api/state.rst @@ -0,0 +1,37 @@ +Parameters and initialization +============================= + +.. currentmodule:: pytensor_ml.params + +Parameters +---------- + +.. autosummary:: + :toctree: generated/ + + TrainableParameter + NonTrainableParameter + StepCounter + trainable + non_trainable + step_counter + +.. currentmodule:: pytensor_ml.state + +Initializers +------------ + +.. autosummary:: + :toctree: generated/ + + Initializer + ZeroInitializer + OneInitializer + NormalInitializer + UnitUniformInitializer + XavierNormalInitializer + XavierUniformInitializer + OrthogonalInitializer + UnrecordedInitializer + initialize_params + fans diff --git a/docs/source/api/util.rst b/docs/source/api/util.rst new file mode 100644 index 0000000..b3b1bd7 --- /dev/null +++ b/docs/source/api/util.rst @@ -0,0 +1,9 @@ +Utilities +========= + +.. currentmodule:: pytensor_ml.util + +.. autosummary:: + :toctree: generated/ + + DataLoader diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..bd6a1cb --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,176 @@ +import os +import sys + +from pathlib import Path + +root_dir = Path("../..").resolve() +sys.path.insert(0, str(root_dir)) +sys.path.insert(0, str(root_dir / "docs" / "sphinxext")) + +import pytensor_ml # noqa: E402 + +# -- Project information ----------------------------------------------------- +project = "pytensor_ml" +copyright = "2025, PyMC Developers" +author = "PyMC Developers" +language = "en" +html_baseurl = "https://pytensor-ml.readthedocs.io" + +# -- Version handling -------------------------------------------------------- +# Mirrors the gEconpy / pytensor pattern so RTD version selector labels match +# what users see in the package. +version = pytensor_ml.__version__ +on_readthedocs = os.environ.get("READTHEDOCS", None) +rtd_version = os.environ.get("READTHEDOCS_VERSION", "") +if on_readthedocs: + if rtd_version.lower() == "stable": + version = pytensor_ml.__version__.split("+")[0] + elif rtd_version.lower() == "latest": + version = "dev" + else: + version = rtd_version +else: + rtd_version = "local" +release = version + +# -- General configuration --------------------------------------------------- +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.autosectionlabel", + "sphinx.ext.intersphinx", + "sphinx.ext.mathjax", + "numpydoc", + "myst_nb", + "sphinx_design", + "sphinx_copybutton", + "sphinx_codeautolink", + "sphinx_sitemap", + "notfound.extension", + "jupyter_sphinx", + "sphinxcontrib.bibtex", + "generate_gallery", +] + +# Bibliographic citations: drop new entries into docs/source/references.bib +# and cite from prose with `{cite:t}` (textual) or `{cite:p}` (parenthetical). +bibtex_bibfiles = ["references.bib"] +bibtex_default_style = "unsrt" +bibtex_reference_style = "author_year" + +# Use the document path as prefix for autosectionlabel anchors so the same +# section title in two files doesn't collide. +autosectionlabel_prefix_document = True + +templates_path = ["_templates"] + +exclude_patterns = [ + "_build", + "**.ipynb_checkpoints", + "*/autosummary/*.rst", + "Thumbs.db", + ".DS_Store", +] + +source_suffix = { + ".rst": "restructuredtext", + ".md": "myst-nb", + ".ipynb": "myst-nb", + ".myst": "myst-nb", +} + +master_doc = "index" + +# -- Autodoc / autosummary --------------------------------------------------- +autosummary_generate = True +autodoc_typehints = "none" +autoclass_content = "class" +# Class method pages live under api/.../classmethods/ — keep them out of the +# global toctree so they don't pollute the sidebar. +remove_from_toctrees = ["**/classmethods/*"] + +numpydoc_show_class_members = False +numpydoc_xref_param_type = True +numpydoc_xref_ignore = { + "of", + "or", + "optional", + "default", + "numeric", + "type", + "scalar", + "instance", + "array", + "array_like", + "1D", + "2D", + "3D", + "nD", + "M", + "N", + "D", + "K", +} + +# -- HTML output ------------------------------------------------------------- +html_theme = "pydata_sphinx_theme" +html_title = "pytensor_ml" +html_short_title = "pytensor_ml" +html_last_updated_fmt = "" + +sitemap_url_scheme = f"{{lang}}{rtd_version}/{{link}}" + +html_theme_options = { + "secondary_sidebar_items": ["page-toc", "edit-this-page", "sourcelink"], + "navbar_start": ["navbar-logo"], + "show_prev_next": True, + "icon_links": [ + { + "url": "https://github.com/pymc-devs/pytensor-ml", + "icon": "fa-brands fa-github", + "name": "GitHub", + "type": "fontawesome", + }, + ], +} + +github_version = version if "." in rtd_version else "main" +html_context = { + "github_url": "https://github.com", + "github_user": "pymc-devs", + "github_repo": "pytensor-ml", + "github_version": github_version, + "doc_path": "docs/source", + "default_mode": "dark", +} + +html_sidebars = {"**": ["sidebar-nav-bs.html", "searchbox.html"]} +html_static_path = ["_static"] + +# -- MyST / MyST-NB config --------------------------------------------------- +myst_enable_extensions = [ + "colon_fence", + "deflist", + "dollarmath", + "amsmath", + "substitution", +] +myst_dmath_double_inline = True + +# Notebooks ship pre-rendered. Re-executing them on RTD would require pinning +# every numerical dep and would slow the build significantly; flip this to +# "auto" or "force" later if the gallery becomes the source of truth. +nb_execution_mode = "off" + +# -- Intersphinx ------------------------------------------------------------- +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "numpy": ("https://numpy.org/doc/stable/", None), + "scipy": ("https://docs.scipy.org/doc/scipy/", None), + "jax": ("https://jax.readthedocs.io/en/latest/", None), + "torch": ("https://docs.pytorch.org/docs/stable/", None), + "pytensor": ("https://pytensor.readthedocs.io/en/latest/", None), + "pymc": ("https://www.pymc.io/projects/docs/en/stable/", None), + "myst": ("https://myst-parser.readthedocs.io/en/latest/", None), + "myst-nb": ("https://myst-nb.readthedocs.io/en/latest/", None), +} diff --git a/docs/source/dev/contributing.rst b/docs/source/dev/contributing.rst new file mode 100644 index 0000000..5b20901 --- /dev/null +++ b/docs/source/dev/contributing.rst @@ -0,0 +1,91 @@ +Contributing +============ + +Contributions are welcome, from a typo fix to a new layer family. + +**Every pull request needs an issue first.** Open one describing what you mean +to change, and wait for a reply before writing the code. The design may already +be settled, the behaviour may be deliberate, or someone may be halfway through +the same work. Link the issue from the pull request. + +Setting up +---------- + +.. code-block:: bash + + git clone https://github.com/pymc-devs/pytensor-ml.git + cd pytensor-ml + pip install -e ".[dev]" + pre-commit install + +The conda environments under ``conda_envs/`` are what CI installs, pinned +harder than the package metadata. Reach for one when a failure reproduces in CI +but not locally: + +.. code-block:: bash + + conda env create -f conda_envs/pytensor_ml.yml + +Docs are built with pixi, which owns its own environment: + +.. code-block:: bash + + pixi run docs-build # build once into docs/build/html + pixi run docs-serve # rebuild on save, served at http://localhost:8000 + +``pixi.lock`` is checked in, and it has to stay that way. It pins the exact +environment a docs build resolves to, so a build that works for you works for +everyone else and for Read the Docs. If a change of yours updates the lock file, +commit it in the same PR as the change that caused it. A lock file that has +drifted out of sync with ``pyproject.toml`` is worse than no lock file, because +it fails somewhere far from the change that broke it. + +Running the tests +----------------- + +.. code-block:: bash + + pytest # everything a core job runs + pytest tests/test_layers.py # one file, while iterating + python scripts/run_mypy.py # the type check CI runs + +The backend dispatch tests under ``tests/dispatch/`` need that backend +installed, and the core environment deliberately installs none of them. One CI +job per backend covers those, and running the core suite with no backend present +proves the library does not quietly depend on one. Install the backend you are +working on to run its tests locally. + +**A new test file has to be added to a CI group.** ``tests/test_workflow_groups.py`` +reads ``.github/workflows/run_tests.yml`` and fails when a test file is in no +group, in two groups, or named by a group but missing from disk. Add the file to +one of the ``test-subset`` entries in the same PR. + +Style and typing +---------------- + +``ruff`` formats and lints, ``mypy`` type-checks ``pytensor_ml/``, and both run +in CI, so a clean ``pre-commit run --all-files`` is the cheapest way to keep a +PR green. There is no allowlist of expected type failures: the codebase is +mypy-clean, and it stays that way. For the conventions no tool enforces, see +the :doc:`style guide `. + +Docstrings are numpydoc. Every public entrypoint carries an ``Examples`` +section whose code is complete and runnable -- imports included, no ``>>>`` +prompts, so a reader can paste it straight into a script. Run a new example +before you submit it; nothing checks that for you yet. + +Working with LLMs +----------------- + +LLM-assisted contributions are welcome, on two conditions. + +**Disclose it.** Say in the pull request that a model was involved, and roughly +how much. A tab-completion here and there is not the same as a generated module, +and a reviewer reads the two differently. + +**You are responsible for every line you submit, not the model.** You understand +what the code does and why, you can defend each decision in review, and you have +run it. Review comments come to you, and "the model wrote it that way" answers +nothing. Code that nobody understands costs more to maintain than no +contribution at all, and a pull request whose author cannot explain it will be +closed. diff --git a/docs/source/dev/docs.rst b/docs/source/dev/docs.rst new file mode 100644 index 0000000..ac59dbf --- /dev/null +++ b/docs/source/dev/docs.rst @@ -0,0 +1,87 @@ +Working on the docs +=================== + +This page covers how the documentation system is wired and the workflows +needed to extend it — adding an API page, a notebook example, or a citation. + +Building locally +---------------- + +The docs build from ``docs/`` using the ``pytensor_ml-docs`` conda +environment: + +.. code-block:: bash + + conda env update -f conda_envs/environment-docs.yml + cd docs + make show # build + open the rendered HTML in the default browser + make livehtml # auto-rebuild + auto-refresh on every save (sphinx-autobuild) + make clean # wipe build/ and all generated source (gallery, thumbnails, autosummary stubs) + +Read the Docs builds the same way; ``.readthedocs.yaml`` points at the same +conda env and ``docs/source/conf.py``. + +Layout +------ + +Source content lives under ``docs/source/``: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Path + - Purpose + * - ``index.rst`` + - Landing page + top-level toctree. + * - ``api.rst`` + ``api/*.rst`` + - Autosummary entry points; one file per public submodule. + * - ``install.rst`` + - Installation guide. Hand-written narrative. + * - ``examples/*.rst`` + - One page per notebook category, in the order set by ``GALLERY_PAGES`` in + ``generate_gallery.py``. A category with no notebooks writes no page, so add its entry to the + toctree in ``index.rst`` along with the first notebook. **Generated** at build time. + * - ``examples//**/*.ipynb`` + - Notebook copies staged from ``examples/``, under the same folders. **Generated**. + * - ``dev/`` + - This page, the contributing guide and the style guide. + * - ``references.bib`` + - BibTeX entries; cited via ``{cite:t}`` or ``{cite:p}``. + * - ``_templates/autosummary/`` + - Sphinx autosummary class template (per-method subpages). + +Build-time-generated paths are gitignored via ``docs/.gitignore``; never +commit anything under ``source/_thumbnails/``, ``source/examples//``, +``source/api/**/generated/``, or ``source/examples/gallery.rst``. + +The custom Sphinx extension lives at ``docs/sphinxext/generate_gallery.py``. +It discovers notebooks under ``examples/``, copies them into +``docs/source/examples//``, extracts thumbnails, and emits +``examples/gallery.rst``. + +Adding an API page +------------------ + +Public objects are documented through ``autosummary`` stubs, so a new class or +function only needs an entry in the relevant ``docs/source/api/*.rst`` file +under the right section heading; the stub page is generated on the next build. +A whole new module gets its own ``api/.rst`` plus a line in the +``api.rst`` toctree. + +Adding a notebook example +------------------------- + +Drop the ``.ipynb`` under ``examples/``. The ``generate_gallery`` extension +auto-discovers it on the next build, extracts the last image output as a +thumbnail, and emits a grid card. Ship the notebook with its outputs already +rendered — ``nb_execution_mode`` is ``"off"``, so nothing is re-run at build +time. + +To group notebooks into named categories, create subdirectories under +``examples/`` (e.g. ``examples/introductory/foo.ipynb``). The subdir name +becomes the category id; pretty titles are looked up in ``CATEGORY_TITLES`` +inside ``generate_gallery.py`` and fall back to title-casing the folder name. + +Notebooks must be tracked by git to appear in the gallery, so untracked +work-in-progress notebooks under ``examples/`` don't pollute the build. diff --git a/docs/source/dev/index.rst b/docs/source/dev/index.rst new file mode 100644 index 0000000..5cd8c58 --- /dev/null +++ b/docs/source/dev/index.rst @@ -0,0 +1,9 @@ +Developer Guide +=============== + +.. toctree:: + :maxdepth: 1 + + contributing + style_guide + docs diff --git a/docs/source/dev/style_guide.rst b/docs/source/dev/style_guide.rst new file mode 100644 index 0000000..033c19b --- /dev/null +++ b/docs/source/dev/style_guide.rst @@ -0,0 +1,246 @@ +Style Guide +=========== + +``ruff`` settles anything mechanical -- formatting, import order, line length -- +and CI runs it, so ``pre-commit run --all-files`` decides those questions before +review does. This page covers the rest: the judgment the tools cannot make. + +Most of it you will get right by writing code that looks like the file +around it. + +Code +---- + +Keep hot paths lean: no redundant checks, no invariant recomputed inside a loop +that could be hoisted out of it, no silent ``O(n^2)`` where ``O(n)`` works. A +network trains for hundreds of thousands of steps, and anything on that path is +paid for that many times. + +Errors should be specific and loud. A bare ``except:``, or an +``except Exception: pass`` that swallows a failure, turns a bug into a mystery +three layers away. Validate input where a wrong value would otherwise surface as +a confusing error deep in a graph, and nowhere else; a check that cannot fire is +noise. + +Where you do raise, name the fix in the message. It reaches the reader at the +moment they need it, which no amount of documentation does: + +.. code-block:: python + + raise ValueError( + f"A fan-scaled initializer needs a parameter of at least two dimensions to size its draws, " + f"but got shape {shape}. A bias or a norm scale has no fans; give it an initializer of its " + "own -- `trainable(value, name, initializer=ZeroInitializer())`." + ) + +Design +------ + +Write the simplest thing that works. Generality for a future that has not +arrived is a cost paid now against a benefit that may never come. Two pieces of +code that look alike today but change for different reasons are not duplication, +and forcing them together couples them wrongly, so the rule of three is a good +prior before extracting a helper. + +Keep one function at one altitude: raw string-mangling next to high-level +orchestration means a helper is missing. Be consistent about failure, too. One +module should not raise for some errors, return ``None`` for others, and return +a sentinel for a third kind of the same failure. + +The usual anti-patterns to watch for: + +* A boolean flag that makes one function do two things, and the ``do_thing(True, + False)`` call site it leads to. +* Parameter lists too long to hold in your head. +* A dict standing in for an object, where a dataclass would say what the fields + are. +* Mutable default arguments, and hidden global state. +* A function that both computes and mutates. + +Naming and shape +---------------- + +A name should say what something is for, so the code reads as its own +documentation. Avoid names that describe a type rather than a role: ``data``, +``tmp``, ``obj``, ``result2``. Single letters are fine where they are the +mathematical convention (``i``, ``x``, a kernel's ``k``) and nowhere else. Name +the same concept the same way the surrounding code does, and name the constants: +a bare ``0.9`` in an update rule tells the reader nothing, where ``decay`` tells +them what it is for. + +Shape carries meaning too. Prefer guard clauses to nesting, so the happy path +stays prominent and error handling sits at the edges. Break up expression soup +with named intermediates, since the name *is* the documentation and costs one +line. When two branches do the same kind of thing, shape them the same way, so +that an asymmetry signals a real difference rather than drift. Within a module, +read top down: public API first, helpers below it, reading order roughly +matching call order. + +Comments +-------- + +Comments explain the **why**; the code already says what it does. Fewer is +better -- every comment can drift out of sync, so it has to change a reader's +understanding to earn its place. A better name usually beats a comment. + +Do not commit: + +* Comments that narrate the code (``# increment the counter``). +* Commented-out code. That is what version control is for. +* Process notes: ``# previously we used a loop here``, ``# fix for #123``, or a + ``TODO`` with no owner and no context. Those belong in the commit message. + +Reflow comment prose to the full line width. Short broken-up lines waste +vertical space for no gain. + +Docstrings +---------- + +Docstrings are numpydoc, and they document the **current contract**. Write each +one as if the function appeared in the codebase fresh today. A reader who cloned +the repo an hour ago should never meet a sentence that only makes sense if they +know what the code used to do. + +That rules out, however technical the prose sounds: explaining current behaviour +by contrasting it with a previous version; references to audits, benchmarks, +pull requests or incidents; and "Notes" sections that exist to justify a recent +change rather than to document an invariant. The *why we changed it* goes in the +commit message, where it stays findable without being in front of everyone who +hits ``?`` in a REPL. + +The rest of the rules: + +* **Active voice.** "Compute the gradient", not "The gradient is computed". +* **Every parameter gets a human-readable type**: ``list of int``, not + ``list[int]``. Describe a genuinely nested type in prose rather than pasting a + type hint into the docstring. +* **Optional arguments say so** -- ``, optional`` on the type line -- and the + **default goes in the last sentence** of the description, not on the type + line. +* **Return values are named**, even when nothing ever binds them. +* **No Raises sections.** The error message is the documentation. +* **No module-level docstrings.** If a module's purpose is not evident from its + name and contents, the fix is a better name or a split. +* **Math goes in** ``.. math::`` **directives**, never as backticked ASCII. Use a + raw string so the backslashes survive. Inline, a mathematical symbol takes a + ``:math:`` role and a code identifier takes double backticks: "the input + :math:`\alpha` (parameter ``alpha``)". +* Cross-reference with Sphinx roles: ``:func:``, ``:class:``, ``:mod:``. + +A short private helper whose name and signature already say everything can go +without a docstring. What it cannot have is a chatty paragraph standing in for a +short structured one: + +.. code-block:: python + + def scale(factor: Rate) -> Transform: + """ + Multiply every step by ``factor``. + + Parameters + ---------- + factor : float or TensorVariable + What each step is multiplied by. A symbolic value, such as one a schedule produced, is + applied on-graph. + + Returns + ------- + transform : Transform + A transform that rescales the updates dict. + """ + +Examples +-------- + +Every public entrypoint carries an ``Examples`` section. Three rules: + +#. **A lead-in sentence, always**, even when the code looks self-evident. Never + open the section with the directive. Where two entrypoints have nearly + identical code, the lead-in is the only thing telling them apart, so it says + what to reach for this one for. +#. ``.. code-block:: python``, **never the** ``>>>`` **prompt.** A prompt cannot + be pasted into a script. +#. **Complete and runnable on its own**, imports included, small and tight. Add a + second block, with its own lead-in, when there is a real fork in usage or a + sharp edge worth showing. + +.. code-block:: rst + + Examples + -------- + Bound the whole update rather than each coordinate, so the direction of the step survives and + only its magnitude is capped: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, chain, clip_by_global_norm, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1e-3), clip_by_global_norm(1.0))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) + +Modern Python +------------- + +The supported floor is Python 3.12, so write for it: + +* PEP 604 unions (``int | None``) and PEP 585 generics (``list[int]``), not + ``Optional`` or ``typing.List``. +* **No** ``from __future__ import annotations``. It is unnecessary here. +* f-strings, context managers, ``pathlib`` over ``os.path`` string-mangling, + ``enumerate`` and ``zip`` over index bookkeeping. +* Comprehensions where they read more clearly than an accumulator loop, and not + where they get dense enough to obscure what is happening. +* **Imports at the top of the module.** A function-local import is warranted + only to break a genuine circular dependency or to guard an optional + dependency, and both cases are obvious from context. +* Public functions and methods carry type hints. They are read as + documentation. + +Tests +----- + +Test code is code, and everything above applies to it -- with one deliberate +exception. **Duplicated setup in tests is usually worth keeping.** A test earns +its value by being auditable as one self-contained block: what was seeded, +sampled, patched and asserted, all visible without jumping to a fixture defined +four hundred lines away. Repeated arrange-phase boilerplate is a smaller cost +than a fragmented test, even at six or eight occurrences. + +Extract a fixture when the block is long enough to bury the assertion it exists +to set up, when it encodes an invariant that must stay identical across tests, +or when a signature change would otherwise mean editing it everywhere. + +Commit messages +--------------- + +Subject line in the imperative, short enough to read at a glance, naming the +thing that changed: "Add windowed gradient mass matrix adapter" beats "Update +mass matrix". + +**Never hard-wrap the body.** One paragraph is one line, however long. Manual +line breaks at 72 characters become unreadable the moment anything reflows them, +and they fossilise a width nothing actually uses. Blank lines separate +paragraphs, and deliberately structured content -- lists, tables, aligned +columns -- keeps its own line breaks. + +A body is worth writing when the *why* is invisible in the diff. It is not worth +writing to restate the diff in prose. + +Cruft +----- + +The diff should look like it was written by someone who cleaned up after +themselves: no leftover ``print`` statements (a pre-commit hook rejects them), +no dead code, no unused imports or locals, no stray scratch files. A file that +genuinely should not be tracked belongs in ``.gitignore``, not deleted and +recreated. + +Every dependency is a liability. Question a new one that the standard library, +NumPy, or PyTensor already covers. diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..95fb1a4 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,80 @@ +pytensor_ml +=========== + +A(nother) deep learning library, built on top of PyTensor. + +Networks are ordinary PyTensor graphs. You build one out of layers, and +everything PyTensor already does — symbolic differentiation, graph rewrites, +and compilation to Numba, C, JAX, PyTorch, or MLX — applies to it unchanged. +Training is a compiled function that takes a batch and returns a loss; there +is no separate runtime or tape. + +That goes all the way down: layers are graph constructors, parameters are +shared variables, and a training step is a compiled function whose updates are +the optimizer. Because a model is only a graph, it composes with any other +PyTensor graph — a PyMC model included — as there is nothing else to +interoperate with. + +pytensor_ml ships the usual layer library (dense, convolutional, recurrent, +attention, normalization), composable optimizers with learning-rate schedules +and step guards, and safetensors-backed serialization that round-trips both +weights and architecture. + +.. note:: + + pytensor_ml is pre-alpha. The API is still moving, and there is no + release-to-release compatibility guarantee yet. + +Quick install +------------- + +.. code-block:: bash + + pip install pytensor-ml + +See the :doc:`installation guide ` for backend extras. + +Quick example +------------- + +.. code-block:: python + + import numpy as np + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import Input, Linear, Sequential + from pytensor_ml.loss import CrossEntropy + from pytensor_ml.model import Model + from pytensor_ml.optim import adam, chain, clip_by_global_norm, cosine_schedule + from pytensor_ml.util import DataLoader + + X_in = Input("X_in", shape=(None, 64)) + network = Sequential( + Linear("fc1", n_in=64, n_out=128), + ReLU(), + Linear("logits", n_in=128, n_out=10), + ) + model = Model(X_in, network(X_in)).initialize(seed=0) + + rule = chain(adam(learning_rate=cosine_schedule(1e-3, total_steps=500)), clip_by_global_norm(1.0)) + loss_fn = CrossEntropy(expect_onehot_labels=True, expect_logits=True, reduction="mean") + step = model.compile_train(rule, loss_fn, ndim_out=2) + + loader = DataLoader(X, y_onehot, batch_size=64, random_state=0) + for _ in range(500): + loss_value = step(*loader()) + + predictions = model.predict(X).argmax(axis=-1) + +See the :doc:`example gallery ` for full end-to-end +walkthroughs. + +.. toctree:: + :maxdepth: 1 + :hidden: + :titlesonly: + + install + examples/gallery + api + dev/index diff --git a/docs/source/install.rst b/docs/source/install.rst new file mode 100644 index 0000000..8fce41e --- /dev/null +++ b/docs/source/install.rst @@ -0,0 +1,87 @@ +Installation +============ + +pytensor_ml runs on Python 3.12 and newer, and depends on PyTensor, NumPy and +safetensors. Nothing else is needed to train a network and save it. + +From PyPI +--------- + +.. code-block:: bash + + pip install pytensor-ml + +The distribution is named ``pytensor-ml``; the package you import is +``pytensor_ml``. + +From source +----------- + +.. code-block:: bash + + git clone https://github.com/pymc-devs/pytensor-ml.git + cd pytensor-ml + pip install -e . + +Optional extras +--------------- + +.. code-block:: bash + + pip install "pytensor-ml[examples]" # matplotlib and tqdm, for the example notebooks + pip install "pytensor-ml[dev]" # test, lint and type-checking tools + +Backends +-------- + +A network is a PyTensor graph, so it compiles to whichever backend PyTensor is +pointed at. Numba is the default and arrives with PyTensor itself, so a plain +install already compiles the whole graph rather than stepping through it op by +op. The rest are ordinary packages you install yourself: + +.. list-table:: + :header-rows: 1 + :widths: 18 26 56 + + * - Mode + - Install + - Notes + * - ``"NUMBA"`` + - included + - The default, and a dependency of PyTensor, so it is already there. + * - ``"C"`` + - included + - Compiles each op to C and calls it from Python. Needs a working C + compiler, which most systems already have. + * - ``"JAX"`` + - ``pip install jax`` + - CPU by default; GPU and TPU need the matching hardware-specific + wheel from the JAX project. + * - ``"PYTORCH"`` + - ``pip install torch`` + - Runs on whichever devices the installed torch build supports. + * - ``"MLX"`` + - ``pip install mlx`` + - Apple silicon only, and unavailable on every other platform. + +pytensor_ml registers its own kernels for convolution, pooling and attention on +Numba, JAX, PyTorch and MLX. Registration is lazy: nothing imports a backend +until a graph is actually compiled against it, so an installed-but-unused +backend costs nothing at import time, and a missing one is only a problem if you +ask for it. + +Development install +------------------- + +.. code-block:: bash + + git clone https://github.com/pymc-devs/pytensor-ml.git + cd pytensor-ml + pip install -e ".[dev]" + pre-commit install + +The conda environments under ``conda_envs/`` are the reference setup CI runs +against, pinned more tightly than the package metadata. Install one of those +when a failure does not reproduce anywhere else. + +See :doc:`/dev/contributing` for the rest of the contributor setup. diff --git a/docs/source/references.bib b/docs/source/references.bib new file mode 100644 index 0000000..f5fe3e2 --- /dev/null +++ b/docs/source/references.bib @@ -0,0 +1,44 @@ +@inproceedings{kingma2015adam, + title = {Adam: A Method for Stochastic Optimization}, + author = {Kingma, Diederik P. and Ba, Jimmy}, + booktitle = {International Conference on Learning Representations}, + year = {2015}, +} + +@inproceedings{loshchilov2019adamw, + title = {Decoupled Weight Decay Regularization}, + author = {Loshchilov, Ilya and Hutter, Frank}, + booktitle = {International Conference on Learning Representations}, + year = {2019}, +} + +@inproceedings{ioffe2015batchnorm, + title = {Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift}, + author = {Ioffe, Sergey and Szegedy, Christian}, + booktitle = {International Conference on Machine Learning}, + year = {2015}, +} + +@article{srivastava2014dropout, + title = {Dropout: A Simple Way to Prevent Neural Networks from Overfitting}, + author = {Srivastava, Nitish and Hinton, Geoffrey and Krizhevsky, Alex and Sutskever, Ilya and Salakhutdinov, Ruslan}, + journal = {Journal of Machine Learning Research}, + volume = {15}, + number = {56}, + pages = {1929--1958}, + year = {2014}, +} + +@inproceedings{vaswani2017attention, + title = {Attention Is All You Need}, + author = {Vaswani, Ashish and Shazeer, Noam and Parmar, Niki and Uszkoreit, Jakob and Jones, Llion and Gomez, Aidan N. and Kaiser, Lukasz and Polosukhin, Illia}, + booktitle = {Advances in Neural Information Processing Systems}, + year = {2017}, +} + +@inproceedings{glorot2010init, + title = {Understanding the Difficulty of Training Deep Feedforward Neural Networks}, + author = {Glorot, Xavier and Bengio, Yoshua}, + booktitle = {International Conference on Artificial Intelligence and Statistics}, + year = {2010}, +} diff --git a/docs/sphinxext/generate_gallery.py b/docs/sphinxext/generate_gallery.py new file mode 100644 index 0000000..06c23ee --- /dev/null +++ b/docs/sphinxext/generate_gallery.py @@ -0,0 +1,318 @@ +# Sphinx plugin that stages every notebook under examples/ into the docs tree, extracts a thumbnail +# from its last image output, and emits the grid-card gallery page. Categories come from the +# subdirectory a notebook sits in; see docs/source/dev/docs.rst. +# Adapted from gEconpy, which adapted it from PyMC / seaborn / mpld3. + +import base64 +import json +import shutil +import subprocess + +from pathlib import Path + +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import sphinx + +from matplotlib import image + +logger = sphinx.util.logging.getLogger(__name__) + +# Repo root: docs/sphinxext/generate_gallery.py -> repo +REPO_ROOT = Path(__file__).resolve().parent.parent.parent +NOTEBOOKS_ROOT = REPO_ROOT / "examples" + +# A notebook's path under examples/ decides where it lands: `examples//
/nb.ipynb` +# puts it in a named section of that page, `examples//nb.ipynb` puts it on the page with no +# section heading, and a notebook at the top level falls to CATCH_ALL_PAGE. Pages appear in the order +# listed here; a page with no notebooks writes no file at all. +GALLERY_PAGES = ( + ("getting_started", "Getting Started", "getting_started"), + ("gallery", "Example Gallery", "gallery"), +) +CATCH_ALL_PAGE = "gallery" + +# Sections are the folders themselves, titled by their folder name. List a folder here to pin where +# it sits on the page (anything unlisted follows, alphabetically), and give it a title only when +# title-casing the folder name would get it wrong. +SECTION_ORDER: tuple[str, ...] = () +SECTION_TITLES: dict[str, str] = {} + +PAGE_TITLE = """ +{title} +{underlines} +""" + +TOCTREE_HEAD = """ +.. toctree:: + :hidden: + +""" + +GRID_HEAD = """ +.. grid:: 1 2 3 3 + :gutter: 4 + +""" + +SECTION_TEMPLATE = """ +.. _gallery-{section_id}: + +{section_title} +{underlines} + +.. grid:: 1 2 3 3 + :gutter: 4 + +""" + +ITEM_TEMPLATE = """ + .. grid-item-card:: :doc:`{doc_name}` + :img-top: {image} + :link: {doc_reference} + :link-type: {link_type} + :shadow: none +""" + + +def is_tracked_by_git(filepath): + try: + result = subprocess.run( + ["git", "ls-files", "--error-unmatch", str(filepath)], + capture_output=True, + check=False, + cwd=REPO_ROOT, + ) + except FileNotFoundError: + return True + else: + return result.returncode == 0 + + +def create_thumbnail(infile, width=275, height=275, cx=0.5, cy=0.5, border=4): + im = image.imread(infile) + rows, cols = im.shape[:2] + size = min(rows, cols) + if size == cols: + xslice = slice(0, size) + ymin = min(max(0, int(cy * rows - size // 2)), rows - size) + yslice = slice(ymin, ymin + size) + else: + yslice = slice(0, size) + xmin = min(max(0, int(cx * cols - size // 2)), cols - size) + xslice = slice(xmin, xmin + size) + thumb = im[yslice, xslice] + thumb[:border, :, :3] = thumb[-border:, :, :3] = 0 + thumb[:, :border, :3] = thumb[:, -border:, :3] = 0 + + dpi = 100 + fig = plt.figure(figsize=(width / dpi, height / dpi), dpi=dpi) + ax = fig.add_axes([0, 0, 1, 1], aspect="auto", frameon=False, xticks=[], yticks=[]) + ax.imshow(thumb, aspect="auto", resample=True, interpolation="bilinear") + fig.savefig(infile, dpi=dpi) + plt.close(fig) + + +class NotebookGenerator: + """Extract a thumbnail and stage a notebook for inclusion in the gallery.""" + + def __init__(self, src_nb: Path, category: str, examples_dir: Path, thumbnails_dir: Path): + self.src_nb = src_nb + self.stripped_name = src_nb.stem + self.category = category + self.staged_nb = examples_dir / category / f"{self.stripped_name}.ipynb" + self.png_path = thumbnails_dir / category / f"{self.stripped_name}.png" + + with src_nb.open(encoding="utf-8") as fid: + self.json_source = json.load(fid) + + def stage_notebook(self): + self.staged_nb.parent.mkdir(parents=True, exist_ok=True) + # Always re-copy: notebooks at the source can change between builds. + shutil.copyfile(self.src_nb, self.staged_nb) + + def extract_preview_pic(self): + pic = None + for cell in self.json_source["cells"]: + for output in cell.get("outputs", []): + if "image/png" in output.get("data", []): + pic = output["data"]["image/png"] + if pic is not None: + return base64.b64decode(pic) + return None + + def gen_previews(self): + self.png_path.parent.mkdir(parents=True, exist_ok=True) + if self.png_path.exists(): + logger.info( + f"Custom thumbnail already exists for {self.src_nb.name}, skipping extraction", + type="thumbnail_extractor", + ) + return + + preview = self.extract_preview_pic() + if preview is not None: + with self.png_path.open("wb") as buff: + buff.write(preview) + create_thumbnail(self.png_path) + else: + logger.warning( + f"No image found in {self.src_nb.name}; its gallery card will have no thumbnail. " + f"Re-run the notebook with its outputs saved, or drop a PNG at {self.png_path}.", + type="thumbnail_extractor", + ) + + +def discover_notebooks() -> dict[tuple[str, str | None], list[Path]]: + """ + Group every notebook under ``examples/`` by the page and section its path puts it in. + + Returns + ------- + grouped : dict mapping tuple to list of pathlib.Path + Notebook paths keyed by ``(page, section)``, where ``section`` is None for a notebook that + sits directly in a page's folder. + """ + if not NOTEBOOKS_ROOT.exists(): + return {} + + grouped: dict[tuple[str, str | None], list[Path]] = {} + for path in sorted(NOTEBOOKS_ROOT.rglob("*.ipynb")): + if ".ipynb_checkpoints" in path.parts: + continue + parts = path.relative_to(NOTEBOOKS_ROOT).parts + page = parts[0] if len(parts) > 1 else CATCH_ALL_PAGE + section = parts[1] if len(parts) > 2 else None + grouped.setdefault((page, section), []).append(path) + return grouped + + +def _section_title(section: str) -> str: + return SECTION_TITLES.get(section, section.replace("_", " ").title()) + + +def _page_layout(grouped): + """ + Lay the discovered notebooks out into pages and the sections within them. + + Returns + ------- + layout : list of tuple of str, str and list of tuple + One entry per page that has notebooks, in the order the pages appear: the document name, its + title, and its sections as ``(section title or None, notebook paths)``. + """ + known_pages = {page for page, _, _ in GALLERY_PAGES} + ordering = {section: index for index, section in enumerate(SECTION_ORDER)} + + def position(section: str | None) -> tuple[bool, int, str]: + # Unsectioned notebooks lead the page; the rest follow SECTION_ORDER, then alphabetically. + return section is not None, ordering.get(section, len(ordering)), section or "" + + layout = [] + for page, page_title, document in GALLERY_PAGES: + # One entry per section, so two folders of the same name land under one heading rather than + # two headings competing for the same label. + merged: dict[str | None, list[Path]] = {} + for (notebook_page, section), paths in grouped.items(): + on_this_page = notebook_page == page or ( + document == CATCH_ALL_PAGE and notebook_page not in known_pages + ) + if on_this_page: + merged.setdefault(section, []).extend(paths) + + if not merged: + continue + + sections = [ + (None if section is None else _section_title(section), merged[section]) + for section in sorted(merged, key=position) + ] + layout.append((document, page_title, sections)) + return layout + + +def main(app): + logger.info("Starting pytensor_ml gallery generation.") + + src_dir = Path(app.builder.srcdir) + examples_dir = src_dir / "examples" + thumbnails_dir = src_dir / "_thumbnails" + examples_dir.mkdir(parents=True, exist_ok=True) + thumbnails_dir.mkdir(parents=True, exist_ok=True) + + grouped = discover_notebooks() + if not grouped: + logger.warning( + "No notebooks found under examples/; no gallery pages will be written.", + type="thumbnail_extractor", + ) + + for document, page_title, sections in _page_layout(grouped): + toctree_entries: list[str] = [] + body: list[str] = [] + + for section_title, nb_paths in sections: + if section_title is None: + body.append(GRID_HEAD) + else: + body.append( + SECTION_TEMPLATE.format( + section_title=section_title, + section_id=section_title.lower().replace(" ", "-"), + underlines="-" * len(section_title), + ) + ) + + for nb_path in nb_paths: + if not is_tracked_by_git(nb_path): + logger.info( + f"Skipping {nb_path.name}, not tracked by git", + type="thumbnail_extractor", + ) + continue + + # Staged under the same folders it came from, so two notebooks sharing a name in + # different sections cannot collide. + relative_dir = nb_path.parent.relative_to(NOTEBOOKS_ROOT) + nbg = NotebookGenerator( + src_nb=nb_path, + category=str(relative_dir) if relative_dir.parts else CATCH_ALL_PAGE, + examples_dir=examples_dir, + thumbnails_dir=thumbnails_dir, + ) + nbg.stage_notebook() + nbg.gen_previews() + + doc_name = f"{nbg.category}/{nbg.stripped_name}" + toctree_entries.append(doc_name) + # Relative to docs/source/ — the leading slash makes Sphinx resolve it from the source + # root, so a hand-supplied thumbnail can be dropped in at the same path. + img_path = f"/_thumbnails/{nbg.category}/{nbg.stripped_name}.png" + body.append( + ITEM_TEMPLATE.format( + doc_name=doc_name, + image=img_path, + doc_reference=doc_name, + link_type="doc", + ) + ) + + # Title, then a hidden toctree so the notebooks register with Sphinx, then the grid cards. + file_lines = [ + PAGE_TITLE.format(title=page_title, underlines="=" * len(page_title)), + TOCTREE_HEAD, + ] + file_lines.extend(f" {entry}\n" for entry in toctree_entries) + file_lines.append("\n") + file_lines.extend(body) + + page_rst = examples_dir / f"{document}.rst" + page_rst.write_text("\n".join(file_lines), encoding="utf-8") + logger.info(f"Wrote {page_title} to {page_rst.relative_to(src_dir)}") + + +def setup(app): + app.connect("builder-inited", main) + return {"parallel_read_safe": True, "parallel_write_safe": True} diff --git a/examples/gallery/mnist_feed_forward.ipynb b/examples/gallery/mnist_feed_forward.ipynb new file mode 100644 index 0000000..a1e828c --- /dev/null +++ b/examples/gallery/mnist_feed_forward.ipynb @@ -0,0 +1,758 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "intro", + "metadata": {}, + "source": [ + "# Feed-forward classifier on MNIST digits\n", + "\n", + "Train a fully-connected network with batch normalization and dropout on scikit-learn's\n", + "handwritten digits, then evaluate it with a confusion matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "00915a61", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:52.027191Z", + "iopub.status.busy": "2026-08-25T02:48:52.027111Z", + "iopub.status.idle": "2026-08-25T02:48:52.173089Z", + "shell.execute_reply": "2026-08-25T02:48:52.172683Z" + } + }, + "outputs": [], + "source": [ + "import pytensor\n", + "\n", + "floatX = \"float32\"\n", + "pytensor.config.floatX = floatX" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fae24c05", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:52.174352Z", + "iopub.status.busy": "2026-08-25T02:48:52.174243Z", + "iopub.status.idle": "2026-08-25T02:48:53.229547Z", + "shell.execute_reply": "2026-08-25T02:48:53.228886Z" + } + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "from sklearn.datasets import load_digits\n", + "from sklearn.preprocessing import MinMaxScaler, OneHotEncoder\n", + "\n", + "from pytensor_ml.activations import LeakyReLU\n", + "from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential\n", + "from pytensor_ml.loss import CrossEntropy\n", + "from pytensor_ml.model import Model\n", + "from pytensor_ml.optim import adagrad\n", + "from pytensor_ml.util import DataLoader" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "65882b64", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:53.230866Z", + "iopub.status.busy": "2026-08-25T02:48:53.230715Z", + "iopub.status.idle": "2026-08-25T02:48:53.240267Z", + "shell.execute_reply": "2026-08-25T02:48:53.239910Z" + } + }, + "outputs": [], + "source": [ + "X, y = load_digits(return_X_y=True)\n", + "y_onehot = OneHotEncoder().fit_transform(y[:, None]).toarray().astype(floatX)\n", + "X_normed = MinMaxScaler().fit_transform(X).astype(floatX)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f81f9076", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:53.241415Z", + "iopub.status.busy": "2026-08-25T02:48:53.241358Z", + "iopub.status.idle": "2026-08-25T02:48:53.244263Z", + "shell.execute_reply": "2026-08-25T02:48:53.243923Z" + } + }, + "outputs": [], + "source": [ + "X_in = Input(\"X_in\", shape=(None, 64))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "41840fac", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:53.245236Z", + "iopub.status.busy": "2026-08-25T02:48:53.245172Z", + "iopub.status.idle": "2026-08-25T02:48:53.279826Z", + "shell.execute_reply": "2026-08-25T02:48:53.279416Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prediction_network = Sequential(\n", + " Linear(\"Linear_1\", n_in=64, n_out=256),\n", + " BatchNorm(\"BatchNorm_1\"),\n", + " Dropout(\"Dropout_1\", p=0.5),\n", + " LeakyReLU(),\n", + " Linear(\"Linear_2\", n_in=256, n_out=128),\n", + " BatchNorm(\"BatchNorm_2\"),\n", + " Dropout(\"Dropout_2\", p=0.5),\n", + " LeakyReLU(),\n", + " Linear(\"Logits\", n_in=128, n_out=10),\n", + ")\n", + "\n", + "y_hat = prediction_network(X_in)\n", + "model = Model(X_in, y_hat, compile_kwargs={\"mode\": \"NUMBA\"})\n", + "model" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3bfa0ddc", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:53.280917Z", + "iopub.status.busy": "2026-08-25T02:48:53.280849Z", + "iopub.status.idle": "2026-08-25T02:48:53.282487Z", + "shell.execute_reply": "2026-08-25T02:48:53.282211Z" + } + }, + "outputs": [], + "source": [ + "loss_fn = CrossEntropy(expect_onehot_labels=True, expect_logits=True, reduction=\"mean\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "290d3191", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:53.283397Z", + "iopub.status.busy": "2026-08-25T02:48:53.283336Z", + "iopub.status.idle": "2026-08-25T02:48:53.747712Z", + "shell.execute_reply": "2026-08-25T02:48:53.747271Z" + } + }, + "outputs": [], + "source": [ + "# `model.compile_train` is the training companion to `model.predict`: it builds the loss against a target,\n", + "# differentiates it, folds in the BatchNorm running-statistic updates, and compiles a one-step training\n", + "# function (reusing the model's NUMBA compile settings).\n", + "step = model.compile_train(adagrad(learning_rate=1e-3), loss_fn, ndim_out=2)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e77b697f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:53.749148Z", + "iopub.status.busy": "2026-08-25T02:48:53.749065Z", + "iopub.status.idle": "2026-08-25T02:48:53.751419Z", + "shell.execute_reply": "2026-08-25T02:48:53.751075Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.initialize()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "dd6dede5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:48:53.752358Z", + "iopub.status.busy": "2026-08-25T02:48:53.752291Z", + "iopub.status.idle": "2026-08-25T02:49:01.599179Z", + "shell.execute_reply": "2026-08-25T02:49:01.598803Z" + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "abe107262e274a1c98bc59c2510f10fc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/10000 [00:00]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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hx4ygYR2twQbiKgOHTrI5s2b/d5evHhxc9DuCwAAKJyCCka0EeXBBx803S2///671KlTJ08Punz5ctN9E02WbD9o9SEAAGBLscF2zXz++efyww8/mFojKSkpZr02wZQoUcJcHjZsmOzatUs++eQTc33kyJFSu3ZtadKkiZw6dUomTJhg8kd0sVrx2CKSnnnGXH55ynr5/oFLrD4kAABsJ6hgZMyYMeZv9+7dsw3xveOOO8xlrSGSmJjouk0DkKFDh5oARQMWDUo016Rv375itaJFYlyXixWlGC0AAAUqgTUaE2CC1fjZaXL81Glz+eI65eWrf3YM2b4BALC7tHAmsBYWMX4uAwCAyLF3MBKTFYK4XQQAABFk62DEXQxtIwAAWMLWwYhHNw0tIwAAWMLWwYh7NEIwAgCANewdjLihmwYAAGsQjJxDywgAANawdTBCmggAANazdTByeeMqrsuHj2dYeiwAANiVrYORuztnTfSXePC4pccCAIBd2ToYiS1K0TMAAKxm62DEHfkjAABYw9bBiHsAUoThNAAAWMLWwYi7jNNnrD4EAABsydbBiMPtctrJTAuPBAAA+7J3MOIejQAAAEvYOxjxaBsBAABWsHUwknmaYAQAAKvZOhg5mXHa6kMAAMD2bB2MZJ6hZQQAAKvZOhg5QzACAIDlbB2M0DICAID1bB2MnKZlBAAAy9k6GIkrauunDwBAVLD1t3HHCytYfQgAANierYORokWYqxcAAKvZOhgBAADWIxgBAACWIhgBAACWIhgBAACWIhgBAACWIhhx898Zm6x7JQAAsCmCETdv/baZ+WoAAIgwghEvMZQeAQAgoghGAACApQhGvDgc1rwQAADYFcEIAACwFMEIAACwFMGIF3ppAACILNsHI89c2TjCpxwAALizfTDSskaCxwkBAACRZftgRMSzsIiD4TQAAESU7YMRipwBAGAtghGLXwAAAOyOYMSraYTRNAAARJbtgxEAAFCAgpERI0ZIu3btpHTp0lKpUiW59tprZePGjTneb/bs2dKmTRuJj4+XunXrytixYyVa0E0DAEABCkY0qHjggQdk4cKFMmPGDMnMzJRevXrJsWPH/N5n27Zt0rdvX+nSpYssX75chg8fLoMHD5ZJkyZJNCawMpgGAIDIig1m42nTpnlc/+ijj0wLydKlS6Vr164+76OtIDVr1pSR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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.plot(loss_history)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "fb38dd99", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:49:01.862156Z", + "iopub.status.busy": "2026-08-25T02:49:01.862036Z", + "iopub.status.idle": "2026-08-25T02:49:02.289368Z", + "shell.execute_reply": "2026-08-25T02:49:02.288834Z" + } + }, + "outputs": [], + "source": [ + "from scipy.special import softmax\n", + "\n", + "# `model.predict` compiles a forward pass specialized for inference: Dropout is dropped and BatchNorm uses its\n", + "# running statistics.\n", + "y_hat_logits = model.predict(X_normed)\n", + "y_hat_probs = softmax(y_hat_logits, axis=-1)\n", + "y_pred = np.argmax(y_hat_probs, axis=-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "4393b9c3", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-25T02:49:02.290781Z", + "iopub.status.busy": "2026-08-25T02:49:02.290698Z", + "iopub.status.idle": "2026-08-25T02:49:02.500943Z", + "shell.execute_reply": "2026-08-25T02:49:02.500631Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "from sklearn.metrics import confusion_matrix\n", + "\n", + "counts = confusion_matrix(y, y_pred)\n", + "\n", + "fig, ax = plt.subplots(figsize=(6, 5.5), dpi=144)\n", + "image = ax.imshow(counts, cmap=\"Blues\")\n", + "\n", + "# White reads on the dark end of the ramp, ink on the light end.\n", + "dark_cell_floor = counts.max() / 2\n", + "\n", + "for (true_digit, predicted_digit), count in np.ndenumerate(counts):\n", + " if count:\n", + " text_color = \"white\" if count > dark_cell_floor else \"0.15\"\n", + " ax.text(\n", + " predicted_digit,\n", + " true_digit,\n", + " count,\n", + " ha=\"center\",\n", + " va=\"center\",\n", + " color=text_color,\n", + " fontsize=8,\n", + " )\n", + "\n", + "ax.set(xlabel=\"Predicted digit\", ylabel=\"True digit\", title=\"Confusion matrix\")\n", + "ax.set_xticks(range(10))\n", + "ax.set_yticks(range(10))\n", + "ax.tick_params(length=0)\n", + "for spine in ax.spines.values():\n", + " spine.set_visible(False)\n", + "fig.colorbar(image, ax=ax, shrink=0.8, label=\"Examples\")\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.6" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": { + "0bcdce547bc8446ba9950b2a6e8999b2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "2.0.0", + "_view_name": "HTMLView", + "description": "", + "description_allow_html": false, + "layout": "IPY_MODEL_ea54cb9334144ea99d84dc21cc7c0ea6", + "placeholder": "​", + "style": "IPY_MODEL_2a298c03a7f041efae80cedf9ab23d08", + "tabbable": null, + "tooltip": null, + "value": " 10000/10000 [00:07<00:00, 2503.90it/s]" + } + }, + "2a298c03a7f041efae80cedf9ab23d08": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "HTMLStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "HTMLStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "StyleView", + "background": null, + "description_width": "", + "font_size": null, + "text_color": null + } + }, + "34cce22552b64a3380060cf22320bfb0": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "2.0.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border_bottom": null, + "border_left": null, + "border_right": null, + "border_top": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "65921c5a2e444a7e91f9d582e65e7407": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "2.0.0", + "_view_name": "HTMLView", + "description": "", + "description_allow_html": false, + "layout": "IPY_MODEL_665e01e9a39d432da11fb7a80eb45a5b", + "placeholder": "​", + "style": "IPY_MODEL_91fd3a5117aa448a8144bce91a69026c", + "tabbable": null, + "tooltip": null, + "value": "100%" + } + }, + "665e01e9a39d432da11fb7a80eb45a5b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "2.0.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border_bottom": null, + "border_left": null, + "border_right": null, + "border_top": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "88c307250c7a4eb19a0cf850d723a947": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "91fd3a5117aa448a8144bce91a69026c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "HTMLStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "HTMLStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "StyleView", + "background": null, + "description_width": "", + "font_size": null, + "text_color": null + } + }, + "9a022c9eaec14e249c4608ec26adc36b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "2.0.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_allow_html": false, + "layout": "IPY_MODEL_34cce22552b64a3380060cf22320bfb0", + "max": 10000.0, + "min": 0.0, + "orientation": "horizontal", + "style": "IPY_MODEL_88c307250c7a4eb19a0cf850d723a947", + "tabbable": null, + "tooltip": null, + "value": 10000.0 + } + }, + "9c6a6dabb2054400b3e72ff114b6c647": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "2.0.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border_bottom": null, + "border_left": null, + "border_right": null, + "border_top": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "abe107262e274a1c98bc59c2510f10fc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "2.0.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_65921c5a2e444a7e91f9d582e65e7407", + "IPY_MODEL_9a022c9eaec14e249c4608ec26adc36b", + "IPY_MODEL_0bcdce547bc8446ba9950b2a6e8999b2" + ], + "layout": "IPY_MODEL_9c6a6dabb2054400b3e72ff114b6c647", + "tabbable": null, + "tooltip": null + } + }, + "ea54cb9334144ea99d84dc21cc7c0ea6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "2.0.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border_bottom": null, + "border_left": null, + "border_right": null, + "border_top": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + } + }, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/mnist_feed_forward.ipynb b/examples/mnist_feed_forward.ipynb deleted file mode 100644 index 043384f..0000000 --- a/examples/mnist_feed_forward.ipynb +++ /dev/null @@ -1,197 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "15279e7f", - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "00915a61", - "metadata": {}, - "outputs": [], - "source": [ - "import pytensor\n", - "\n", - "floatX = \"float32\"\n", - "pytensor.config.floatX = floatX" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fae24c05", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "\n", - "from sklearn.datasets import load_digits\n", - "from sklearn.preprocessing import MinMaxScaler, OneHotEncoder\n", - "\n", - "from pytensor_ml.activations import LeakyReLU\n", - "from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential\n", - "from pytensor_ml.loss import CrossEntropy\n", - "from pytensor_ml.model import Model\n", - "from pytensor_ml.optim import adagrad\n", - "from pytensor_ml.util import DataLoader" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "65882b64", - "metadata": {}, - "outputs": [], - "source": [ - "X, y = load_digits(return_X_y=True)\n", - "y_onehot = OneHotEncoder().fit_transform(y[:, None]).toarray().astype(floatX)\n", - "X_normed = MinMaxScaler().fit_transform(X).astype(floatX)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f81f9076", - "metadata": {}, - "outputs": [], - "source": [ - "X_in = Input(\"X_in\", shape=(None, 64))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "41840fac", - "metadata": {}, - "outputs": [], - "source": [ - "prediction_network = Sequential(\n", - " Linear(\"Linear_1\", n_in=64, n_out=256),\n", - " BatchNorm(\"BatchNorm_1\"),\n", - " Dropout(\"Dropout_1\", p=0.5),\n", - " LeakyReLU(),\n", - " Linear(\"Linear_2\", n_in=256, n_out=128),\n", - " BatchNorm(\"BatchNorm_2\"),\n", - " Dropout(\"Dropout_2\", p=0.5),\n", - " LeakyReLU(),\n", - " Linear(\"Logits\", n_in=128, n_out=10),\n", - ")\n", - "\n", - "y_hat = prediction_network(X_in)\n", - "model = Model(X_in, y_hat, compile_kwargs={\"mode\": \"NUMBA\"})\n", - "model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3bfa0ddc", - "metadata": {}, - "outputs": [], - "source": [ - "loss_fn = CrossEntropy(expect_onehot_labels=True, expect_logits=True, reduction=\"mean\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "290d3191", - "metadata": {}, - "outputs": [], - "source": [ - "# `model.compile_train` is the training companion to `model.predict`: it builds the loss against a target,\n", - "# differentiates it, folds in the BatchNorm running-statistic updates, and compiles a one-step training\n", - "# function (reusing the model's NUMBA compile settings).\n", - "step = model.compile_train(adagrad(learning_rate=1e-3), loss_fn, ndim_out=2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e77b697f", - "metadata": {}, - "outputs": [], - "source": [ - "model.initialize()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dd6dede5", - "metadata": {}, - "outputs": [], - "source": [ - "from tqdm.notebook import tqdm\n", - "\n", - "loader = DataLoader(X_normed, y_onehot)\n", - "loss_history = []\n", - "n_epochs = 10_000\n", - "\n", - "for _ in tqdm(range(n_epochs)):\n", - " X_batch, y_batch = loader()\n", - " loss_value = step(X_batch, y_batch)\n", - " loss_history.append(loss_value)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ab1ad6ef", - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "plt.plot(loss_history)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fb38dd99", - "metadata": {}, - "outputs": [], - "source": [ - "from scipy.special import softmax\n", - "\n", - "# `model.predict` compiles a forward pass specialized for inference: Dropout is dropped and BatchNorm uses its\n", - "# running statistics.\n", - "y_hat_logits = model.predict(X_normed)\n", - "y_hat_probs = softmax(y_hat_logits, axis=-1)\n", - "y_pred = np.argmax(y_hat_probs, axis=-1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4393b9c3", - "metadata": {}, - "outputs": [], - "source": [ - "import seaborn as sns\n", - "\n", - "from sklearn.metrics import confusion_matrix\n", - "\n", - "sns.heatmap(confusion_matrix(y, y_pred), annot=True, fmt=\"0.0f\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..d2734aa --- /dev/null +++ b/pixi.lock @@ -0,0 +1,10749 @@ +version: 7 +platforms: +- name: linux-64 +- name: osx-arm64 +- name: win-64 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h13e7031_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.7-h399a421_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - pypi: https://files.pythonhosted.org/packages/01/a4/9b63d595d748e3aff8812b65eacc1a2c4bd90b7c2012e08e72373b4835eb/filelock-3.32.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/26/885774c006de6620ed3d10f45d8e20fe0b8e6aad6d573211a2cbc8b3e528/numba-0.66.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/28/50/f203ff3a3ddfe19308efc83c5a3a29ed02bf786732ec35e68bf9162f3365/safetensors-0.8.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4d/da/007be278565871eadd1ce7abda66532cecda68b63363be44f321f3600c43/pytensor-3.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6b/89/2a844506d49651e9aa1af6ef95b6bd8031cb1d5a4375edec6155037e04cf/scipy-1.18.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/95/9c/c510029fc6ef33a6275cd2c5d3cecd6613dfd6aa401d57c54f1c18852ccf/setuptools-84.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/e1/05b50692b647cac3c18200ac485b04f342f00ed173c9cc46767274469a15/llvmlite-0.48.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.1-hf6b4638_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-hca69786_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.3-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.7-hf4d206d_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + - pypi: https://files.pythonhosted.org/packages/01/a4/9b63d595d748e3aff8812b65eacc1a2c4bd90b7c2012e08e72373b4835eb/filelock-3.32.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/49/59ea385dc3a62ff498ddf3cfff7c2b41b0f9f9d3c4122b3f1dcb6d6327fe/scipy-1.18.1-cp314-cp314-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/8d/8e/8170f2e0c217f88069c333d85bb976e536b332aecfcce606ddbdb249385f/llvmlite-0.48.0-cp314-cp314-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/95/9c/c510029fc6ef33a6275cd2c5d3cecd6613dfd6aa401d57c54f1c18852ccf/setuptools-84.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/7a/7e0e73550eb4e41ede6e72fb5371f4539537a4d770a3b73fa9b61aea0622/numba-0.66.0-cp314-cp314-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/9e/74/3b17e08f1d9facfa7772ed32e1614f2e676f44093b2b717dae89a0c44161/pytensor-3.3.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f5/b1/fa7c600e7dceae12e9606c7578cbc9ff1e1ed55844883ee5c92205e86226/safetensors-0.8.0-cp310-abi3-macosx_11_0_arm64.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.1-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.3-hf411b9b_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.7-h53f6dd8_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + - pypi: https://files.pythonhosted.org/packages/01/a4/9b63d595d748e3aff8812b65eacc1a2c4bd90b7c2012e08e72373b4835eb/filelock-3.32.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/4d/0eae213c5197c6a0cb4080f984c7295cb53af6d0ecba9ece190a6ae9560f/pytensor-3.3.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/1b/6d/3fba214c1e5e0f69991677ec3bc17023f0421776975e1de0c682dca475e2/safetensors-0.8.0-cp310-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/52/94/d73da0d28f16c45bb9b0a5691b91610b0275c5ef0eb5e43c87cf2dc1bf31/scipy-1.18.1-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/66/c5/b46ad28ac3681d035ea21365c5e052149062e1a0a9affd0563d2760ea6ff/numba-0.66.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/95/9c/c510029fc6ef33a6275cd2c5d3cecd6613dfd6aa401d57c54f1c18852ccf/setuptools-84.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c9/2d/6a5171fb7236ac0895e1a02ccba3735bf291e8597239aa6421894d3c0ba8/llvmlite-0.48.0-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl + docs: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16.1-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-26.1.0-py314h89acca1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/blas-2.309-mkl.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/blas-devel-3.11.0-9_hcf00494_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-h505cf86_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-h9908984_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314hcd2bdb6_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.1.1-py314h8d76f0c_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-16.2.0-hf8037ed_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py314h97ea11e_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hac629b4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.21-py314h42812f9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/double-conversion-3.4.0-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.3-h4db4eae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-16.2.0-hc6a0c74_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-16.2.0-h176d5d0_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.15-h54a6638_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.5.5-py314h42812f9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-16.2.0-hc6a0c74_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-16.2.0-h0d273dc_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py314h97ea11e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.2.0-hdb68285_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-9_h5875eb1_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-h39a168f_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-ha411449_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-h018ffa1_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-9_hfef963f_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h0acdd01_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_h5f7f9d4_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-hd45a770_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.129-h7cc23a3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h373387f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h5e6c136_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.2.0-h69a702a_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.3-h45c3219_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-14.3.1-h23af247_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-9_h5e43f62_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapacke-3.11.0-9_hdba1596_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-h474f4eb_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h922cc85_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.6-h9d76c99_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libraqm-0.11.0-h6406941_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-16.2.0-h3048135_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.22-hebe6cf0_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h13e7031_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.2.0-hdf11a46_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.2-h9d88235_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.357.0-h0e34353_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-hb83e432_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.38-h280c20c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.13.2-h51789e4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h3206bd6_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvmlite-0.48.0-py314h8f0570d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.11.1-py314h815e797_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.11.1-py314h9a9c090_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-2026.1.0-hecca717_244.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-devel-2026.1.0-ha770c72_244.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-include-2026.1.0-ha770c72_244.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-service-2.8.0-py314h3e0429d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.66.0-py314h42812f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.13-hbde042b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pandoc-3.10.2-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-h8b3dc9c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.3.0-py314h8ec4b1a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314hfe1a184_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb03c661_1003.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyside6-6.11.2-py314h5d85b37_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pytensor-3.3.0-py314ha04e0d8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pytensor-base-3.3.0-np2py314h6477eea_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.7-h399a421_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.2.0-py312h8a5ba0d_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/qt6-main-6.11.2-pl5321h9df5c37_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.6.3-py314h7e8cd81_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/safetensors-0.8.0-py314h2e6c369_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.0-py314hf07bd8e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.52-py314h0f05182_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2023.0.0-hab88423_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.8-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/watchfiles-1.2.0-py314h1bee95f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.26.0-h1964d1d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-17.0.1-py314h518bba1_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 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-keysyms-0.4.1-hb711507_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-renderutil-0.3.10-hb711507_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-wm-0.4.2-hb711507_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.48-h280c20c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-h280c20c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-h0d788c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.7-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.3-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-h7cc23a3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-h7cc23a3_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.7-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xorgproto-2025.1-h280c20c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-hebe6cf0_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hce19668_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.14.2-pyhcf101f3_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/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.7.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.7.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.2-pyhc90fa1f_0.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/noarch/cpython-3.14.7-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22.4-pyhd8ed1ab_0.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.32.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - 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/noarch/fonttools-4.63.0-pyh7db6752_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.19-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.3.0-pyha191276_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.16.1-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.9-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/jedi-0.20.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.15.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.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.26.0-hcf101f3_1.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-builder-1.2.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-cache-1.0.1-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-sphinx-0.5.3-pyha770c72_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.1-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.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.20.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.6.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.17-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/latexcodec-2.0.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-16.2.0-he3ce08f_104.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-16.2.0-h86e191b_104.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdit-py-plugins-0.6.1-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/noarch/mistune-3.3.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-5.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.17.1-hb502eef_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.17.1-h08b4883_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.11.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio2-1.7.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.6.2-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/noarch/numpydoc-1.10.0-pyhcf101f3_0.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-26.3-pyhc364b38_0.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.7-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.11.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.26.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.53-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.53-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybtex-0.26.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybtex-docutils-1.0.3-pyhcf101f3_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydata-sphinx-theme-0.20.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.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.22.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.7-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.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/roman-numerals-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - 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.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.9.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-9.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-autobuild-2025.8.25-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-codeautolink-0.19.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-copybutton-0.5.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-last-updated-by-git-0.3.8-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-notfound-page-1.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-sitemap-2.9.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-bibtex-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda + - 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-2.0.0-pyhd8ed1ab_0.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/starlette-1.6.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tabulate-0.10.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.16.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.16.0-h69aa097_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.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-2026c-h151e31d_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.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.52.4-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-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/widgetsnbextension-4.0.16-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda + - pypi: . + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.14.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-1.0.0-pyhcf101f3_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/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.7.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.7.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.2-pyhc90fa1f_0.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/noarch/compiler-rt22_osx-arm64-22.1.8-hb8825d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-22.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.7-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22.4-pyhd8ed1ab_0.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.32.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - 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/noarch/fonttools-4.63.0-pyh7db6752_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.19-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.3.0-pyh01cf8df_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.16.1-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.9-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/jedi-0.20.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.15.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.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.26.0-hcf101f3_1.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-builder-1.2.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-cache-1.0.1-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-sphinx-0.5.3-pyha770c72_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.1-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.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.20.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.6.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.17-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/latexcodec-2.0.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-22.1.8-h707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdit-py-plugins-0.6.1-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/noarch/mistune-3.3.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-5.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.17.1-hb502eef_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.17.1-h08b4883_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.11.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio2-1.7.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.6.2-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/noarch/numpydoc-1.10.0-pyhcf101f3_0.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-26.3-pyhc364b38_0.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.7-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.11.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.26.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.53-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.53-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybtex-0.26.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybtex-docutils-1.0.3-pyhcf101f3_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydata-sphinx-theme-0.20.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.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.22.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.7-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.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/roman-numerals-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - 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.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.9.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-9.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-autobuild-2025.8.25-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-codeautolink-0.19.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-copybutton-0.5.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-last-updated-by-git-0.3.8-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-notfound-page-1.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-sitemap-2.9.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-bibtex-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda + - 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-2.0.0-pyhd8ed1ab_0.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/starlette-1.6.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tabulate-0.10.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.16.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.16.0-h69aa097_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.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-2026c-h151e31d_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.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.52.4-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-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/widgetsnbextension-4.0.16-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-26.1.0-py314h61c6340_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/blas-2.309-accelerate.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/blas-devel-3.11.0-9_h55bc449_accelerate.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-hf00d406_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-he4a93e4_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314hee34562_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.4-he0f2337_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm22_1_hbe26303_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm22_1_h7bf7afb_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.1.1-py314h618e29d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-22-22.1.8-default_h54a73ef_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-22.1.8-default_cfg_ha85103e_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-22.1.8-default_h79071a4_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-22.1.8-default_h79071a4_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-22.1.8-default_cfg_h9e28d6e_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-22.1.8-default_h350d358_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-22.1.8-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt22-22.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/contourpy-1.3.3-py314hf8a3a22_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.21-py314he609de1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.18.3-h81aa574_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.14.3-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.16-h84a0fba_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.15-h784d473_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/greenlet-3.5.5-py314he609de1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py314hf8a3a22_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.19.1-hdfa7624_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm22_1_h5b97f1b_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm22_1_h692d5aa_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.2.0-h1eee2c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-9_h3d1d584_accelerate.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-h1dcdb26_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-h5295a6a_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-h2ddc9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-9_h752f6bc_accelerate.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp22.1-22.1.8-default_h79071a4_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-22.1.8-default_h54a73ef_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-22.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-22.1.8-h6dc3340_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-he7e0567_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321h26f1114_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.1-hf6b4638_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.3-h2ed5691_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.88.3-ha531971_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libharfbuzz-14.3.1-hcda0f7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.2.0-h84a0fba_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-9_hcb0d94e_accelerate.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapacke-3.11.0-9_hbdd07e9_accelerate.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm22-22.1.8-h759d1ac_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.58-hf5e6511_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libraqm-0.11.0-h45af499_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.22-h74c22ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-hca69786_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.2-h282da08_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h202fb40_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hbffa61f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h5ef1a60_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.3-h5654f7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.8-hc225544_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22-22.1.8-h79441dc_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22.1.8-hdb3d66b_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvmlite-0.48.0-py314h582f951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-3.11.1-py314h314fc0d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-base-3.11.1-py314h27b0870_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numba-0.66.0-py314h705d3de_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.6-py314hb79c6fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.3-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandoc-3.10.2-hce30654_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.47-he63d830_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pillow-12.3.0-py314hab283cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.4-h784d473_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314hd98292b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-h84a0fba_1003.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.2.2-py314h63b12ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.2.2-py314hddd3963_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pytensor-3.3.0-py314h0ac4119_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pytensor-base-3.3.0-np2py314hdd732f0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.7-hf4d206d_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.2.0-py312hcedbef1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.6.3-py314hc05cd11_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/safetensors-0.8.0-py314h54f3292_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.18.0-py314h18e1515_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.52-py314h5583935_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.8-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.1-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/watchfiles-1.2.0-py314he1d1ac0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-17.0.1-py314h2fbedac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-h84a0fba_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h74c22ad_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h10816f8_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-h31dac16_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + - pypi: . + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.14.2-pyhcf101f3_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/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.7.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.7.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.2-pyh6dadd2b_0.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/noarch/cpython-3.14.7-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22.4-pyhd8ed1ab_0.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.32.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + - 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/noarch/fonttools-4.63.0-pyh7db6752_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.19-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.3.0-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.16.1-pyhe2676ad_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.9-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/jedi-0.20.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.15.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.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.26.0-hcf101f3_1.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-builder-1.2.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-cache-1.0.1-pyhff2d567_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-sphinx-0.5.3-pyha770c72_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.1-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-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.20.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.6.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.17-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/latexcodec-2.0.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_win-64-16.1.0-hecf7705_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_win-64-16.1.0-hc76ffd0_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/m2w64-sysroot_win-64-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdit-py-plugins-0.6.1-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/noarch/mingw-w64-ucrt-x86_64-crt-git-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mingw-w64-ucrt-x86_64-headers-git-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mingw-w64-ucrt-x86_64-windows-default-manifest-6.4-he206cdd_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mingw-w64-ucrt-x86_64-winpthreads-git-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.3.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-5.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.17.1-hb502eef_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.17.1-h08b4883_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.11.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio2-1.7.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.6.2-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/noarch/numpydoc-1.10.0-pyhcf101f3_0.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-26.3-pyhc364b38_0.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.7-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.11.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.26.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.53-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.53-hd8ed1ab_0.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/pybtex-0.26.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybtex-docutils-1.0.3-pyhcf101f3_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pydata-sphinx-theme-0.20.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.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.22.2-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.7-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.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/roman-numerals-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + - 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.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.9.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-9.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-autobuild-2025.8.25-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-codeautolink-0.19.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-copybutton-0.5.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-last-updated-by-git-0.3.8-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-notfound-page-1.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-sitemap-2.9.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-bibtex-2.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda + - 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-2.0.0-pyhd8ed1ab_0.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/starlette-1.6.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tabulate-0.10.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.16.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.16.0-h69aa097_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.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-2026c-h151e31d_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.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.52.4-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-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/widgetsnbextension-4.0.16-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-26.1.0-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/binutils_impl_win-64-2.46.1-default_ha84baeb_102.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/blas-2.309-mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/blas-devel-3.11.0-9_h85df5b5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-1.2.0-hc8c2fe1_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-bin-1.2.0-hd477307_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314h85cf176_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cairo-1.18.4-h477c42c_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.1.1-py314h5a2d7ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/conda-gcc-specs-16.1.0-h851ee6d_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/contourpy-1.3.3-py314hf309875_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.21-py314hb98de8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/double-conversion-3.4.0-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fontconfig-2.18.3-hd47e2ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/freetype-2.14.3-h57928b3_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fribidi-1.0.16-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gcc-16.1.0-hb5e953d_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gcc_impl_win-64-16.1.0-hf3f8c13_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/graphite2-1.3.15-h5112557_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/greenlet-3.5.5-py314hb98de8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gxx-16.1.0-hb5e953d_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gxx_impl_win-64-16.1.0-he3d2c83_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/kiwisolver-1.5.0-py314hf309875_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lcms2-2.19.1-hf2c6c5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ld_impl_win-64-2.46.1-default_hfd38196_102.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lerc-4.2.0-hd936e49_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-9_h8455456_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.2.0-hf02afa3_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.2.0-h84f9c24_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.2.0-he2a975b_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-9_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-22.1.8-default_hacd6ee9_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libdeflate-1.25-h1a1d4e4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.1-hac47afa_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype-2.14.3-h57928b3_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype6-2.14.3-hdbac1cb_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgcc-16.1.0-h110b43a_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libglib-2.88.3-he810d59_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgomp-16.1.0-h8ee18e1_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libharfbuzz-14.3.1-h03b5201_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.13.0-default_h049141e_1000.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libintl-0.22.5-h5728263_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libjpeg-turbo-3.2.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-9_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapacke-3.11.0-9_h3ae206f_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.58-hdc8cecf_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libraqm-0.11.0-h50d6d30_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.22-h6a83c73_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libstdcxx-16.1.0-hae5796f_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libtiff-4.7.2-h8f73337_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libvulkan-loader-1.4.357.0-h477610d_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxcb-1.17.0-h874e120_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h3cfd58e_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-h8ef44ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxslt-1.1.43-h0fbe4c1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.8-h4fa8253_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvmlite-0.48.0-py314h46b4103_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/m2-conda-epoch-20250515-0_x86_64.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/matplotlib-3.11.1-py314h30c6bc1_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/matplotlib-base-3.11.1-py314h2061cd4_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_234.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-devel-2026.1.0-h57928b3_234.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-include-2026.1.0-h57928b3_234.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-service-2.8.0-py314h6d79c4c_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numba-0.66.0-py314hb98de8c_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.4.6-py314h02f10f6_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.5.4-h0e57b4f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.3-hf411b9b_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pandoc-3.10.2-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pcre2-10.47-h8466c1e_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pillow-12.3.0-py314h61b30b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pixman-0.46.4-h5112557_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pthread-stubs-0.4-hba3369d_1003.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyside6-6.11.2-py314h447aaf0_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pytensor-3.3.0-py314h443d124_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pytensor-base-3.3.0-np2py314hb7a55bc_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.7-h53f6dd8_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-312-py314hf700ef7_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-3.0.5-py314h51f0985_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.2.0-py312h343a6d4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/qhull-2020.2-hc790b64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/qt6-main-6.11.2-pl5321hfcac499_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-2026.6.3-py314h9f07db2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/safetensors-0.8.0-py314h9f07db2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.18.0-py314h221f224_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/sqlalchemy-2.0.52-py314hc5dbbe4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-hd3d4ead_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.8-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/unicodedata2-17.0.1-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/watchfiles-1.2.0-py314hc980628_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/websockets-17.0.1-py314h13f4da2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h3a581c9_11.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + - pypi: . +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 28948 + timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda + build_number: 7 + sha256: c0cddb66070dd6355311f7667ce2acccf70d1013edaa6e97f22859502fefdb22 + md5: 887b70e1d607fba7957aa02f9ee0d939 + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - _openmp_mutex >=4.5 + size: 8244 + timestamp: 1764092331208 +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16.1-hb03c661_0.conda + sha256: cf93ca0f1f107e95a35969a4622684e08fcb8cf37f8cf4a1e9e424828386c921 + md5: 8904e09bda369377b3dd07e2ac828c5d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: LGPL-2.1-or-later + license_family: LGPL + purls: [] + run_exports: + weak: + - alsa-lib >=1.2.16.1,<1.3.0a0 + size: 592377 + timestamp: 1781521980743 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-26.1.0-py314h89acca1_0.conda + sha256: 1b39b6275fd72e7d180d64dda68862f6f9598b2542552205fffad6a329323094 + md5: a4cf00be4eed0c82b87dfd7173ca6723 + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=2.0.0b1 + - libgcc >=15 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + run_exports: {} + size: 33021 + timestamp: 1787248105067 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda + sha256: fb7bf36984a37ce7e4714d1d1da0bd0e3bfc679520f5cdc184afc676fd4b5da2 + md5: a0c5e0b7f58c8ceeb08e5bc41251d5a2 + depends: + - ld_impl_linux-64 2.46.1 default_hbd61a6d_102 + - sysroot_linux-64 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + run_exports: {} + size: 3713752 + timestamp: 1784214522814 +- conda: https://conda.anaconda.org/conda-forge/linux-64/blas-2.309-mkl.conda + build_number: 9 + sha256: 9c4602333f515e8f39e1807a81cc693a4fb87f2fccd9ca90b8d4441c58d886e5 + md5: 9dd0f025349a526353ea91dd9cdf599b + depends: + - blas-devel 3.11.0 9*_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 18170 + timestamp: 1786059133387 +- conda: https://conda.anaconda.org/conda-forge/linux-64/blas-devel-3.11.0-9_hcf00494_mkl.conda + build_number: 9 + sha256: cf440e3dc59cf08d83116c4cd196beab485e08c8641703e93c0dccbc595f51cd + md5: 9163a094430cead29b0e1bf6149ce384 + depends: + - libblas 3.11.0 9_h5875eb1_mkl + - libcblas 3.11.0 9_hfef963f_mkl + - liblapack 3.11.0 9_h5e43f62_mkl + - liblapacke 3.11.0 9_hdba1596_mkl + - mkl >=2026.1.0,<2027.0a0 + - mkl-devel 2026.1.* + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 17790 + timestamp: 1786059022192 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-h505cf86_3.conda + sha256: 1f2ccfebe6e0113bfc473b21906372c1ee4eb69bf6faef0ad7f3d4d79af63a98 + md5: 6ff307b78fbfb7dcafb7e25ff8bc9c10 + depends: + - __glibc >=2.17,<3.0.a0 + - brotli-bin 1.2.0 h9908984_3 + - libbrotlidec 1.2.0 ha411449_3 + - libbrotlienc 1.2.0 h018ffa1_3 + - libgcc >=15 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 20676 + timestamp: 1786622810792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-h9908984_3.conda + sha256: 56b2e5e8a49f9887af74cc63e0d55a3654e60b667ad5558da089549a36ae6a0c + md5: 8929291d9efc59715df1cfa7daf5e3ed + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlidec 1.2.0 ha411449_3 + - libbrotlienc 1.2.0 h018ffa1_3 + - libgcc >=15 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 21598 + timestamp: 1786622801722 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314hcd2bdb6_3.conda + sha256: e52ff7e1e3c5f4423421fbcd1f1ebf1d6ce123e22890ceb225d6552b7bbc551f + md5: bd1be0851060138e038f6f4e09cc1eb4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 h39a168f_3 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=compressed-mapping + run_exports: {} + size: 367948 + timestamp: 1786622843866 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + sha256: 1a0d382c515ebf55f8ee1f38c8b81bc95af5c2acc42ad53b66bc5df932032f96 + md5: e675fabcf81499adc7edf58124fb1e01 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 257808 + timestamp: 1785906269155 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda + sha256: 06525fa0c4e4f56e771a3b986d0fdf0f0fc5a3270830ee47e127a5105bde1b9a + md5: bb6c4808bfa69d6f7f6b07e5846ced37 + depends: + - __glibc >=2.17,<3.0.a0 + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.1,<79.0a0 + - libexpat >=2.7.3,<3.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + - libgcc >=14 + - libglib >=2.86.3,<3.0a0 + - libpng >=1.6.53,<1.7.0a0 + - libstdcxx >=14 + - libxcb >=1.17.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - pixman >=0.46.4,<1.0a0 + - xorg-libice >=1.1.2,<2.0a0 + - xorg-libsm >=1.2.6,<2.0a0 + - xorg-libx11 >=1.8.12,<2.0a0 + - xorg-libxext >=1.3.6,<2.0a0 + - xorg-libxrender >=0.9.12,<0.10.0a0 + license: LGPL-2.1-only or MPL-1.1 + purls: [] + run_exports: + weak: + - cairo >=1.18.4,<2.0a0 + size: 989514 + timestamp: 1766415934926 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.1.1-py314h8d76f0c_2.conda + sha256: 9d181949eead0d4092ed9ffa3b7ec066a15572d515327939c8a074c224262528 + md5: 314853abf64fc052dea08bd17df17b65 + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + run_exports: {} + size: 306626 + timestamp: 1786775112485 +- conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-16.2.0-hf8037ed_4.conda + sha256: 24825798d2b016cfa873485bc1bfb31bba32d7c8a4e8a3ab991165536523b79c + md5: d30388235d4b77c78289bf93573c57cf + depends: + - gcc_impl_linux-64 >=16.2.0,<16.2.1.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 32505 + timestamp: 1787618879364 +- conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py314h97ea11e_4.conda + sha256: b0314a7f1fb4a294b1a8bcf5481d4a8d9412a9fee23b7e3f93fb10e4d504f2cc + md5: 95bede9cdb7a30a4b611223d52a01aa4 + depends: + - numpy >=1.25 + - python + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/contourpy?source=hash-mapping + run_exports: {} + size: 324013 + timestamp: 1769155968691 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hac629b4_1.conda + sha256: 7684da83306bb69686c0506fb09aa7074e1a55ade50c3a879e4e5df6eebb1009 + md5: af491aae930edc096b58466c51c4126c + depends: + - __glibc >=2.17,<3.0.a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=13 + - libntlm >=1.8,<2.0a0 + - libstdcxx >=13 + - libxcrypt >=4.4.36 + - openssl >=3.5.5,<4.0a0 + license: BSD-3-Clause-Attribution + license_family: BSD + purls: [] + run_exports: + weak: + - cyrus-sasl >=2.1.28,<3.0a0 + size: 210103 + timestamp: 1771943128249 +- conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda + sha256: 8bb557af1b2b7983cf56292336a1a1853f26555d9c6cecf1e5b2b96838c9da87 + md5: ce96f2f470d39bd96ce03945af92e280 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - libglib >=2.86.2,<3.0a0 + - libexpat >=2.7.3,<3.0a0 + license: AFL-2.1 OR GPL-2.0-or-later + purls: [] + run_exports: + weak: + - dbus >=1.16.2,<2.0a0 + size: 447649 + timestamp: 1764536047944 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.21-py314h42812f9_0.conda + sha256: c16696b23e1d75b6eea7d0c8b9c31c03d1987eeb61852f09b6d4042ca015acd3 + md5: a7eb8029c4fe320c0179085707017c2d + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + run_exports: {} + size: 2842115 + timestamp: 1780390153580 +- conda: https://conda.anaconda.org/conda-forge/linux-64/double-conversion-3.4.0-hecca717_0.conda + sha256: 40cdd1b048444d3235069d75f9c8e1f286db567f6278a93b4f024e5642cfaecc + md5: dbe3ec0f120af456b3477743ffd99b74 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - double-conversion >=3.4.0,<3.5.0a0 + size: 71809 + timestamp: 1765193127016 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.3-h4db4eae_1.conda + sha256: 5a3eb10b18a97223ab06b3a7f0d7f56658db2f2800e2f2af95836fe3bf55ba63 + md5: 922776b528a470ab5afa81fd42abfa1d + depends: + - __glibc >=2.17,<3.0.a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=15 + - libuuid >=2.42.2,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + size: 296288 + timestamp: 1786667377340 +- conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_2.conda + sha256: 612a8e0c1a6ecae23da54d81ef395f6ebb5c8e4468ec2611593ebce75876a4e0 + md5: 2d0ea23b23603e07ca47f23f949f67b6 + depends: + - libfreetype 2.14.3 ha770c72_2 + - libfreetype6 2.14.3 h5e6c136_2 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + size: 175239 + timestamp: 1786641011029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fribidi-1.0.16-hb03c661_1.conda + sha256: 4846a3ca0402f3fe33ad84ed50ab213c6aafde4a0faef3c5002f6bf753e21671 + md5: 1cd10eda5692519d01bb20e086e214c9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - fribidi >=1.0.16,<2.0a0 + size: 61782 + timestamp: 1785912528684 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-16.2.0-hc6a0c74_4.conda + sha256: 1c974f7e764250ddf8ea314553c99412dad37da593f756028c7e2640953e50e6 + md5: 2918c9054a9556dab9bef29861ddd927 + depends: + - conda-gcc-specs + - gcc_impl_linux-64 16.2.0 h176d5d0_4 + license: BSD-3-Clause + purls: [] + run_exports: {} + size: 29416 + timestamp: 1787618988431 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-16.2.0-h176d5d0_4.conda + sha256: d09c1e8ae19bc03a6336516fb2b55f09d1b86bbe16242d911dbf4d23f709b5d5 + md5: 15426bff4573d78ab030e6d439fc820b + depends: + - binutils_impl_linux-64 >=2.46.1 + - libgcc >=16.2.0 + - libgcc-devel_linux-64 16.2.0 he3ce08f_104 + - libgomp >=16.2.0 + - libsanitizer 16.2.0 h3048135_4 + - libstdcxx >=16.2.0 + - libstdcxx-devel_linux-64 16.2.0 h86e191b_104 + - sysroot_linux-64 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 86474258 + timestamp: 1787618763737 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.15-h54a6638_1.conda + sha256: 7fa3b6a9c081fa3e545573152a788d061a0a0ba57df7251cc0f4f75225fc93e7 + md5: f9fe2984587fa8235a6af6004760cd18 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + license: LGPL-2.0-or-later + license_family: LGPL + purls: [] + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 + size: 102835 + timestamp: 1786118485753 +- conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.5.5-py314h42812f9_0.conda + sha256: 8077b6042be044d2c571d5eb340a1ad7a1949534113fb8d9cafb213982b7c60b + md5: a0423baf08abf2f98136e8cc103e46dd + depends: + - python + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/greenlet?source=compressed-mapping + run_exports: {} + size: 278368 + timestamp: 1786384047792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-16.2.0-hc6a0c74_4.conda + sha256: a34a318620ab87f253f99fc41d9da5ace5762beb1f8dcb35d006ccaa07fc5b32 + md5: dbed457da766863500b5a751fa78bfbe + depends: + - conda-gcc-specs + - gcc 16.2.0 hc6a0c74_4 + - gxx_impl_linux-64 16.2.0 h0d273dc_4 + license: BSD-3-Clause + purls: [] + run_exports: {} + size: 28811 + timestamp: 1787619084791 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-16.2.0-h0d273dc_4.conda + sha256: 839b4701fa8eb6b315b28ac8a245310b08aec62893a64727d7cabf260467281a + md5: d7f18a0ab325cc612bfd7842bf53756e + depends: + - gcc_impl_linux-64 16.2.0 h176d5d0_4 + - libstdcxx-devel_linux-64 16.2.0 h86e191b_104 + - sysroot_linux-64 + - tzdata + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 17668584 + timestamp: 1787618949985 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda + sha256: 9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae432 + md5: 72a381cbad04f24b1c2a43ef707f45b4 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14459115 + timestamp: 1786545741408 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-h7cc23a3_1.conda + sha256: dd053c96dcb0dcfd59422aefea9d2fe937a190167f34fba7893ec1e10a7e8963 + md5: ba55d1b89fd7775e67de8291029b4059 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - keyutils >=1.6.3,<2.0a0 + size: 135295 + timestamp: 1786739238128 +- conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py314h97ea11e_0.conda + sha256: e3488ea4a336f29e57de8f282bf40c0505cfc482e03004615e694b48e7d9c79f + md5: 7397e418cab519b8d789936cf2dde6f6 + depends: + - python + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/kiwisolver?source=hash-mapping + run_exports: {} + size: 77363 + timestamp: 1773067048780 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbc21106_2.conda + sha256: 2a5c38c85e63df84c4e69ee71439841ce570d259ae3060627bb9a49a938d66f4 + md5: 53318d715316929a574f83591308b1f8 + depends: + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=15 + - libstdcxx >=15 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 1394333 + timestamp: 1786762112514 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_1.conda + sha256: 112b5b9462572d970f4abd2912f76a25ee7db158b1e7260163d91dd8a630db84 + md5: 8b3ce45e929cd8e8e5f4d18586b56d8b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - libtiff >=4.7.1,<4.8.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - lcms2 >=2.19.1,<3.0a0 + size: 251971 + timestamp: 1780211695895 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda + sha256: 27d83f1188cd19bcb7754a078b3fa7f4cfb8527f8eb2fde54dd01fc529d1adec + md5: 449500f2c089da11c40f5c21312e3e07 + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.46.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + run_exports: {} + size: 745303 + timestamp: 1784214507189 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.2.0-hdb68285_0.conda + sha256: bf9fdebf55d8bc99d83531cdffda00703f4dc5f93a1a956768c147362c72feda + md5: fb9d356b1a57d6d54768be7ebd5fce09 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - lerc >=4.2.0,<5.0a0 + size: 271158 + timestamp: 1785036167977 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-9_h5875eb1_mkl.conda + build_number: 9 + sha256: a8c8b832fb56469221612e1f33c1c01868146c85721966b663a35d4248121e7e + md5: 1c05815b5b3742a5f4398d94fec7aa11 + depends: + - mkl >=2026.1.0,<2027.0a0 + constrains: + - blas 2.309 mkl + - libcblas 3.11.0 9*_mkl + - liblapack 3.11.0 9*_mkl + - liblapacke 3.11.0 9*_mkl + track_features: + - blas_mkl + - blas_mkl_2 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 + size: 18489 + timestamp: 1786058995640 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-h39a168f_3.conda + sha256: e5864f257f839ffc27d681659bac95901f524f602b9121e5dcc5e2df18437f2d + md5: 7a2499a177753582fb7ae7e9dc4a908a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + size: 80265 + timestamp: 1786622773969 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-ha411449_3.conda + sha256: dad31b6d104973deb89710929a35651033aad692d4e7793cdb5b786a9bd54678 + md5: 6ab3315dc56618d652c1da42a648a129 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 h39a168f_3 + - libgcc >=15 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 34828 + timestamp: 1786622783405 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-h018ffa1_3.conda + sha256: d37124d0f51816e7d5e3a94bfc9ed3d6174d077f9b4f832d20c5a08b52bebf1f + md5: 2ac965638d4c6b2b38383bb1aebaf543 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 h39a168f_3 + - libgcc >=15 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 + size: 298639 + timestamp: 1786622792145 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-9_hfef963f_mkl.conda + build_number: 9 + sha256: 8ce1b4cdc6e0feb53c5f8e3cf69b1b2c034f5e2726a4027b2fa6feeb0e7fb93e + md5: cbdd209a7b8cef670cc50830428a3b9d + depends: + - libblas 3.11.0 9_h5875eb1_mkl + constrains: + - blas 2.309 mkl + - liblapack 3.11.0 9*_mkl + - liblapacke 3.11.0 9*_mkl + track_features: + - blas_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 + size: 18097 + timestamp: 1786059002112 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h0acdd01_9.conda + sha256: 91acd638bc94afb56a5192fd15214977e92bd56f8050a1482fab1383775fd194 + md5: 465f5e508f83cef46cb056c1b5ceae7e + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - libxml2 + - libxml2-16 >=2.15.3 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libllvm22 >=22.1.8,<22.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + weak: + - libclang-cpp22.1 >=22.1.8,<22.2.0a0 + size: 24529647 + timestamp: 1787349870338 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_h5f7f9d4_9.conda + sha256: b1a62c3e6328c911e209ffe873e2bee5d8c66b50352c59fc88efd91be12d3bf2 + md5: ae740654c4a0e3731d07fc1162924ca6 + depends: + - libclang-cpp22.1 ==22.1.8 default_h0acdd01_9 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - libxml2 + - libxml2-16 >=2.15.3 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libllvm22 >=22.1.8,<22.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + weak: + - libclang13 >=22.1.8 + size: 14558259 + timestamp: 1787349870338 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda + sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c + md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 + depends: + - __glibc >=2.17,<3.0.a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - libcups >=2.3.3,<2.4.0a0 + size: 4518030 + timestamp: 1770902209173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-hd45a770_1.conda + sha256: 82e134c8a08b1eed9a2ed8ab578b89aa1730dcde3dea8dd87645ed0637878e54 + md5: 40f9b31aa9cf007789867df0decd0492 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 + size: 73710 + timestamp: 1785908694612 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.129-h7cc23a3_0.conda + sha256: ea46b0ca0fa16af1f8b329b740e6cd8b4577c5378fa8717b28a885f70668633d + md5: 64cc91512b6278c315349dc13c53f680 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libpciaccess >=0.19,<0.20.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libdrm >=2.4.129,<2.5.0a0 + size: 313461 + timestamp: 1786684701973 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h373387f_1.conda + sha256: 6473eb8caf2aae830f37caa93db9b26dddf7ac84b63229e8bf7fc0e5c3ab95b0 + md5: 50708d3b951d0f8e2d7f2df5b5edc040 + depends: + - ncurses + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - ncurses >=6.6,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libedit >=3.1.20250104,<3.2.0a0 + size: 135098 + timestamp: 1786616658086 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_5.conda + sha256: 13d3fde9c1dcf254968cc70652222a43f25d04e69555ccf855553110e753288e + md5: 3a1b41c4591a0a1734382af3e2b8bc08 + depends: + - __glibc >=2.17,<3.0.a0 + - libglvnd 1.7.0 ha4b6fd6_5 + license: LicenseRef-libglvnd + purls: [] + run_exports: {} + size: 46694 + timestamp: 1787310030923 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-devel-1.7.0-ha4b6fd6_5.conda + sha256: fd2794bbcff7e692fb476c17886702702893d074071d429217bad7cfb072abfd + md5: 577800fc8c9d8b7d9727246bbfde704e + depends: + - __glibc >=2.17,<3.0.a0 + - libegl 1.7.0 ha4b6fd6_5 + - libgl-devel 1.7.0 ha4b6fd6_5 + - xorg-libx11 + license: LicenseRef-libglvnd + purls: [] + run_exports: + weak: + - libegl >=1.7.0,<2.0a0 + size: 31242 + timestamp: 1787310065866 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda + sha256: 16feffd9ddbbe5b718515d38ee376c685ba95491cd901244e24671d20b952a77 + md5: b24d3c612f71e7aa74158d92106318b2 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.8.1.* + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 77856 + timestamp: 1781203599810 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h3435931_0.conda + sha256: ac38603008bf1e99b8ed379b1a656a67a70e2841f2b6a069c630cdf6316012d2 + md5: 0abe40a9880086ca4d2e5daf09dceff9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 67576 + timestamp: 1783520858222 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_2.conda + sha256: fb12ecb46c30d18d928c0e8fc346ab13b5f6fc8a9cacae4f2f4bb188782586f5 + md5: f8054e759d0ddddaf34a5c8fedc900a1 + depends: + - libfreetype6 >=2.14.3 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: {} + size: 8407 + timestamp: 1786641007099 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h5e6c136_2.conda + sha256: ec607dd5445dd17ff6bf8b7fe6832e5504c226dd91d3aaea7ba83569808b0ce4 + md5: b72a266a9317036fd0464cb98b027cd0 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - freetype >=2.14.3 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: {} + size: 387671 + timestamp: 1786641006460 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_4.conda + sha256: 24090e675d34403b4ee1cd4372d8f6c0937da7ecfd66a19a57cac2ed0f4ea793 + md5: cba14d01083fc62ffd32c24d7d390633 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==16.2.0=*_4 + - libgomp 16.2.0 he0feb66_4 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 1058083 + timestamp: 1787618680111 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.2.0-h69a702a_4.conda + sha256: d8e66c14e23f2b3c70410cff5979d9d357e6edfb990b28d8e630852f4d395629 + md5: b3e52878163a841f6fb951989cc0b217 + depends: + - libgcc 16.2.0 ha9f2e26_4 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: + strong: + - libgcc + size: 28403 + timestamp: 1787618684957 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-16.2.0-h69a702a_4.conda + sha256: 7653be4d88a4d74676c38dd892914d027dcecc0c65c406be772d31cb641f8cfd + md5: 5e92b8413fd1c8f8f3006f4661b12def + depends: + - libgfortran5 16.2.0 h6b99dfc_4 + constrains: + - libgfortran-ng ==16.2.0=*_4 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 28377 + timestamp: 1787618711732 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-16.2.0-h6b99dfc_4.conda + sha256: a5510cbcea3b9e9ab24b336429de997fa727af1dba323031500a962a20e38600 + md5: c22348a769bb072b6184eb6f7f05e4f2 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=16.2.0 + constrains: + - libgfortran 16.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 2526008 + timestamp: 1787618692926 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_5.conda + sha256: 7b2e7e31e8a4f5a01c45ecadcd8aa68c8f733b035240bc7ba9881835ef4bf7b4 + md5: 81141db127a106eb5a91df69a29c9918 + depends: + - __glibc >=2.17,<3.0.a0 + - libglvnd 1.7.0 ha4b6fd6_5 + - libglx 1.7.0 ha4b6fd6_5 + license: LicenseRef-libglvnd + purls: [] + run_exports: {} + size: 131988 + timestamp: 1787310049847 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-devel-1.7.0-ha4b6fd6_5.conda + sha256: 3bebdbeb3ce451287794dddd5cc4d7f4970aac200b2fb797f0d17ac727a71cb7 + md5: f5f7fc038c611a25b22758c0a40d25c9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgl 1.7.0 ha4b6fd6_5 + - libglx-devel 1.7.0 ha4b6fd6_5 + license: LicenseRef-libglvnd + purls: [] + run_exports: + weak: + - libgl >=1.7.0,<2.0a0 + size: 116212 + timestamp: 1787310061570 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.3-h45c3219_1.conda + sha256: 4499458124bcf0bd45e8bd17576f9f007cb1373cb3b01659105443f522bab45c + md5: 533cb021c1bfeba9f720e669cd863fdf + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - pcre2 >=10.47,<10.48.0a0 + - libzlib >=1.3.2,<2.0a0 + - libiconv >=1.18,<2.0a0 + - libffi >=3.7.0,<3.8.0a0 + constrains: + - glib >2.66 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - libglib >=2.88.3,<3.0a0 + size: 4755172 + timestamp: 1786457663614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_5.conda + sha256: 6eb77601a44b78c4631d886d54ef54f321c2bdc69fdefc4065a1e0491f030c76 + md5: cfcf11edcfd4acf0094771a9c3b8587f + depends: + - __glibc >=2.17,<3.0.a0 + license: LicenseRef-libglvnd + purls: [] + run_exports: {} + size: 133827 + timestamp: 1787310026653 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_5.conda + sha256: d1f0d51aea6bcc5d915969cbed32e72a8ed6a95931b87357ef8d0866573688c4 + md5: 614e10aae180f87b84f0d1ca8ceb7d9e + depends: + - __glibc >=2.17,<3.0.a0 + - libglvnd 1.7.0 ha4b6fd6_5 + - xorg-libx11 >=1.8.13,<2.0a0 + license: LicenseRef-libglvnd + purls: [] + run_exports: {} + size: 79834 + timestamp: 1787310042550 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-devel-1.7.0-ha4b6fd6_5.conda + sha256: aff3841e3404d78e1887fef988ca4842930c577399d566fa0980808756b1df51 + md5: fb00b4fb800f2d431303a5c1625ef9d0 + depends: + - __glibc >=2.17,<3.0.a0 + - libglx 1.7.0 ha4b6fd6_5 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-xorgproto + license: LicenseRef-libglvnd + purls: [] + run_exports: + weak: + - libglx >=1.7.0,<2.0a0 + size: 27698 + timestamp: 1787310053582 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_4.conda + sha256: 0fe5cb8e0752241ab55e11656ed1b9726248b522d23b929fe7c95b83eb55b9bb + md5: 89d2c1231f47bd818f5d624b9411459d + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 639968 + timestamp: 1787618616266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libharfbuzz-14.3.1-h23af247_0.conda + sha256: a4eac5a21b84e0fc753b72de01781f634fc9ab70fd32a28d6a40a19700c9188a + md5: 29709e61096dd490fff9e833e4c869f6 + depends: + - __glibc >=2.17,<3.0.a0 + - cairo >=1.18.4,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=15 + - libglib >=2.88.3,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libstdcxx >=15 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 1353639 + timestamp: 1786970872936 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda + sha256: 5041d295813dfb84652557839825880aae296222ab725972285c5abe3b6e4288 + md5: c197985b58bc813d26b42881f0021c82 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - libxml2 + - libxml2-16 >=2.14.6 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libhwloc >=2.13.0,<2.13.1.0a0 + size: 2436378 + timestamp: 1770953868164 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda + sha256: f943117edb9cd4d9c61cc972eee5a34291dc55ea7a6e9e38da104995841cbcb6 + md5: f92233bf33e24a25668bb2119e2c51f9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: LGPL-2.1-only + purls: [] + run_exports: + weak: + - libiconv >=1.18,<2.0a0 + size: 789471 + timestamp: 1787033836207 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.2.0-hb03c661_1.conda + sha256: bba8538e6538ed58a8479b332337b96986561f975d06cfa2039a016c2d246ee4 + md5: 898d1c9793eaa52efc4727bd84d2e39a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + purls: [] + run_exports: + weak: + - libjpeg-turbo >=3.2.0,<4.0a0 + size: 650434 + timestamp: 1785896381946 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-9_h5e43f62_mkl.conda + build_number: 9 + sha256: 3060d9393e7013a192eb55354def1a522348baa57c3ce4dc9cb904bf392a9ac1 + md5: 255025c2d2df85b72c9ab3105f7611e4 + depends: + - libblas 3.11.0 9_h5875eb1_mkl + constrains: + - blas 2.309 mkl + - libcblas 3.11.0 9*_mkl + - liblapacke 3.11.0 9*_mkl + track_features: + - blas_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 + size: 18128 + timestamp: 1786059007914 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapacke-3.11.0-9_hdba1596_mkl.conda + build_number: 9 + sha256: 68f7318c0859627e58708d8eb6e297a945f9c04bff29672ea9e6351791be4c88 + md5: 8a4e244b80d9239f7ab7a2d1d5786d55 + depends: + - libblas 3.11.0 9_h5875eb1_mkl + - libcblas 3.11.0 9_hfef963f_mkl + - liblapack 3.11.0 9_h5e43f62_mkl + constrains: + - blas 2.309 mkl + track_features: + - blas_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - liblapacke >=3.11.0,<3.12.0a0 + size: 18141 + timestamp: 1786059016380 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-h474f4eb_2.conda + sha256: cfc90781f703b8b8cc35694d46c9a200e3cf66657f55517f8b1ec1f672c42752 + md5: d70196b03134e3bab985d9f5554fb38b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + run_exports: + weak: + - libllvm22 >=22.1.8,<22.2.0a0 + size: 44652037 + timestamp: 1787288437518 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + sha256: 9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab + md5: 1390b7c5ac0b1d8e447bc5efa6d3c8c2 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 112995 + timestamp: 1786348617826 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + sha256: 46820b4a835e175940ae20bec00fdddaff804cda27a1408ab1b95e77a2196437 + md5: fcfed1dc5053eb1901b66e7b1fc32588 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 92759 + timestamp: 1786650399772 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda + sha256: 3b3f19ced060013c2dd99d9d46403be6d319d4601814c772a3472fe2955612b0 + md5: 7c7927b404672409d9917d49bff5f2d6 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - libntlm >=1.8,<2.0a0 + size: 33418 + timestamp: 1734670021371 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_5.conda + sha256: 7bdca717c840e17d7dd050f925dd964da61086c2612b8579a4ff4147105f291f + md5: d207a2e9bae9da476bc0a603215d5167 + depends: + - __glibc >=2.17,<3.0.a0 + - libglvnd 1.7.0 ha4b6fd6_5 + license: LicenseRef-libglvnd + purls: [] + run_exports: {} + size: 50627 + timestamp: 1787310045795 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.19-hb03c661_1.conda + sha256: addc80c69d362a9e6c40305c493139a8e9ee504b2f45a6687dbdaa9da3c6183c + md5: 35fa2b34bbced424e6976d30f5fde576 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libpciaccess >=0.19,<0.20.0a0 + size: 30070 + timestamp: 1785971678815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h922cc85_1.conda + sha256: c19eefb87d70d9b4b0629fa48414a155a47a1be4f04583ae71ed8c5a9a32fdcb + md5: fcf71c8d979148873f6f8ad4cfc73d86 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: zlib-acknowledgement + purls: [] + run_exports: + weak: + - libpng >=1.6.58,<1.7.0a0 + size: 316643 + timestamp: 1786616563127 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.6-h9d76c99_0.conda + sha256: b1eb210c180fda9c445b11cba1286ec250ce2c2a85ccb0551a4ed5423df51e68 + md5: 72e019c04ed02a179da38c56965802d1 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=15 + - openldap >=2.6.13,<2.7.0a0 + - openssl >=3.5.7,<4.0a0 + license: PostgreSQL + purls: [] + run_exports: + weak: + - libpq >=18.6,<19.0a0 + size: 2719680 + timestamp: 1786641133110 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libraqm-0.11.0-h6406941_0.conda + sha256: ab3ccb9fd5816f76b18ee8974d359cd2605ca87d8ddef55369dc461b9986f95c + md5: 3ac89a48d224409739dbf6200e524373 + depends: + - libgcc >=14 + - __glibc >=2.28,<3.0.a0 + - fribidi >=1.0.16,<2.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libharfbuzz >=14.2.1 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libraqm >=0.11.0,<0.12.0a0 + size: 33983 + timestamp: 1784850267262 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-16.2.0-h3048135_4.conda + sha256: d08ce38542e0b7782572dbed7eac9d648aad8fd951a82346d93a5d5a78e50232 + md5: fbc8b8b630d4dfa30a7a0b673367cf37 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=16.2.0 + - libstdcxx >=16.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: + weak: + - libsanitizer 16.2.0 + size: 8194231 + timestamp: 1787618720100 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.22-hebe6cf0_2.conda + sha256: 7454c6a7cf27033757f2895bc5e3941fe27604506edd62cf6bc00e50ab015a43 + md5: 42c585f153c17b790cd01f01553d24a1 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + license: ISC + purls: [] + run_exports: + weak: + - libsodium >=1.0.22,<1.0.23.0a0 + size: 269985 + timestamp: 1787225747011 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h13e7031_1.conda + sha256: f20d70da54e5b31dd4a51fb1efeaafafd5ab6dd8d7ac9d1438eaa2526ac4ed3d + md5: e72bbec309c2b0f37823ee7d4fabfcd3 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 974348 + timestamp: 1787051145557 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_4.conda + sha256: 40b792b0186c1e8859280a1f6f19a54fc50a11b32724fc7b637009c1a9bd302b + md5: 2f2ef0d96de5bdd8c1270ff22fdf9352 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 16.2.0 ha9f2e26_4 + constrains: + - libstdcxx-ng ==16.2.0=*_4 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 6613148 + timestamp: 1787618704262 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.2.0-hdf11a46_4.conda + sha256: 4cdebd87b76cf53a58a08ebd6d15336daa79c5f0aa34d83a895ac503c0203632 + md5: de0dceacf3e33c5fc88e167885dc8274 + depends: + - libstdcxx 16.2.0 h934c35e_4 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: + strong: + - libstdcxx + size: 28459 + timestamp: 1787618737021 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.2-h9d88235_0.conda + sha256: b31346e1c01ab40a170e91147092ee8fd92b1dee3c66ee47ef025571c879b159 + md5: c1fcb4a88bc15a9f77ad8d27d7af1df9 + depends: + - __glibc >=2.17,<3.0.a0 + - lerc >=4.1.0,<5.0a0 + - libdeflate >=1.25,<1.26.0a0 + - libgcc >=14 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libstdcxx >=14 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + purls: [] + run_exports: + weak: + - libtiff >=4.7.2,<4.8.0a0 + size: 452337 + timestamp: 1783084902636 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda + sha256: 9b1bdce27a7e31f7d241aeecff67a1f3101d52a2b1e33ccc2cdf2613072bf81f + md5: 01bb81d12c957de066ea7362007df642 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libuuid >=2.42.2,<3.0a0 + size: 40017 + timestamp: 1781625522462 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.357.0-h0e34353_2.conda + sha256: a70c25b66321ee77f9892b205e3247263c400803f543dc8aca53d569a59c5a77 + md5: c5f5f159b66332152197893427071695 + depends: + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgcc >=15 + - xorg-libxrandr >=1.5.5,<2.0a0 + - xorg-libx11 >=1.8.13,<2.0a0 + constrains: + - libvulkan-headers 1.4.357.0.* + license: Apache-2.0 + purls: [] + run_exports: + weak: + - libvulkan-loader >=1.4.357.0,<2.0a0 + size: 206957 + timestamp: 1787491938583 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_1.conda + sha256: 8415001414f488c85b72b9d8cc2071dfb3981a47bc3c8eb56ef91a57d12eae7f + md5: 9332b53d0ea93c5d39e33be03a0c611a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 + size: 428430 + timestamp: 1785954557217 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-hb83e432_1.conda + sha256: ce25a1efa85a78a3ce3b16721d9c36153814adbf2fb004a15f72ec69894b4cb1 + md5: 64e856c420205b009da26471d3ac161d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - pthread-stubs + - xorg-libxau >=1.0.12,<2.0a0 + - xorg-libxdmcp >=1.1.5,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxcb >=1.17.0,<2.0a0 + size: 397355 + timestamp: 1787077466600 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.38-h280c20c_0.conda + sha256: f7e9292dd219a6435bbb1223da9586c3e70d66d169c5a92f08db3f2127df04e9 + md5: f7a7ff5a6ab331e037abd34f379a631d + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - libxcrypt >=4.4.38 + size: 101957 + timestamp: 1785887123445 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.13.2-h51789e4_1.conda + sha256: d44878d396713ccf3b355df617f61c40a1442fffcf134392bc6ce0e6c2219369 + md5: f888787e0eab7a8076a67d197e155ffc + depends: + - xkeyboard-config + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libxcb >=1.17.0,<2.0a0 + - xorg-libxau >=1.0.12,<2.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + license: MIT AND MIT-open-group AND HPND AND HPND-sell-variant AND ISC + purls: [] + run_exports: + weak: + - libxkbcommon >=1.13.2,<2.0a0 + size: 942571 + timestamp: 1787178780572 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_1.conda + sha256: 087d4de023f22d6a28b9e1b818961dd41e9bda6e9793590600ff16ca150bf9cb + md5: 20e4d67ec908f0405124f11612c48305 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - libxml2 2.15.3 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 559721 + timestamp: 1787237579170 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_1.conda + sha256: a16a576a5844a3a0e1cdfc5e162b9fe9c64dccf6a93f44c293bb42851aebe2b4 + md5: 2d34cdb31014cbc8f1e9384c89ede0a5 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.3 hca6bf5a_1 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.3 + size: 46203 + timestamp: 1787237584107 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda + sha256: 0694760a3e62bdc659d90a14ae9c6e132b525a7900e59785b18a08bb52a5d7e5 + md5: 87e6096ec6d542d1c1f8b33245fe8300 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libxml2 + - libxml2-16 >=2.14.6 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxslt >=1.1.43,<2.0a0 + size: 245434 + timestamp: 1757963724977 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + sha256: eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc736 + md5: 0de0122d9570a8ab637c6b73db268389 + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 63713 + timestamp: 1785362952714 +- conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h3206bd6_1.conda + sha256: cf74ea3b6c8f0c01ae3cea10ff9451e4475eb39ee99a2c0f1f1627630ef888e5 + md5: dc2ace17c0da02fbb8273e139f84e7ce + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - intel-openmp <0.0a0 + - openmp 22.1.8|22.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + strong: + - llvm-openmp >=22.1.8 + - _openmp_mutex >=4.5 + - _openmp_mutex * *_llvm + size: 6112252 + timestamp: 1787293213024 +- conda: https://conda.anaconda.org/conda-forge/linux-64/llvmlite-0.48.0-py314h8f0570d_1.conda + sha256: f6ef7e67ad5fa82ab6697caa69b6b76df90264b43a6ac5e23b695156d514e7a8 + md5: 869536d88f55c6235d75805533e30868 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + - python_abi 3.14.* *_cp314 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/llvmlite?source=hash-mapping + run_exports: {} + size: 40440148 + timestamp: 1784043436170 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf + md5: 9a17c4307d23318476d7fbf0fedc0cde + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + run_exports: {} + size: 27424 + timestamp: 1772445227915 +- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.11.1-py314h815e797_2.conda + sha256: 5dc6c469ed94cba223272ba70be250b5820e88640c8fdfe4ae85b2966b8d4b67 + md5: 19db05d03d18c1746c2212bc83e9c4c2 + depends: + - matplotlib-base >=3.11.1,<3.11.2.0a0 + - pyside6 >=6.7.2 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - tornado >=5 + license: PSF-2.0 + license_family: PSF + purls: [] + run_exports: {} + size: 15007 + timestamp: 1785211130117 +- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.11.1-py314h9a9c090_2.conda + sha256: d76657ece6fef30e44fca988a0a884cf5744f2fb1611814c5c993700148fbefa + md5: 57f668cbc4b70c11ea9d19ebed67295e + depends: + - __glibc >=2.17,<3.0.a0 + - contourpy >=1.0.1 + - cycler >=0.10 + - fonttools >=4.28.2 + - freetype + - kiwisolver >=1.3.1 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libgcc >=14 + - libraqm >=0.11.0,<0.12.0a0 + - libstdcxx >=14 + - numpy >=1.25 + - numpy >=1.25,<3 + - packaging >=20.0 + - pillow >=9 + - pyparsing >=3 + - python >=3.14,<3.15.0a0 + - python-dateutil >=2.7 + - python_abi 3.14.* *_cp314 + - qhull >=2020.2,<2020.3.0a0 + - tk >=8.6.13,<8.7.0a0 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/matplotlib?source=hash-mapping + run_exports: {} + size: 9068707 + timestamp: 1785211110030 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-2026.1.0-hecca717_244.conda + sha256: 0b903cfa21b1a3396b3468d41b8112d49a5bd7ff6642305791caca3af33fbaf2 + md5: 3575c034d908c0567c53ed6a33e9dfd9 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex * *_llvm + - _openmp_mutex >=4.5 + - libgcc >=14 + - libstdcxx >=14 + - llvm-openmp >=22.1.8 + - tbb >=2023.0.0 + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + run_exports: {} + size: 143113179 + timestamp: 1786085943810 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-devel-2026.1.0-ha770c72_244.conda + sha256: 89b3d2e21c0ac6bb4a0b0495473a8fdda939bf9a50871091cd64e52d640a67ec + md5: b87e47f06086656b84565cb1d72ea244 + depends: + - mkl 2026.1.0 hecca717_244 + - mkl-include 2026.1.0 ha770c72_244 + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + run_exports: + weak: + - mkl >=2026.1.0,<2027.0a0 + size: 40085 + timestamp: 1786086192776 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-include-2026.1.0-ha770c72_244.conda + sha256: 71cd5db20b5f75183614b814473af582db9dcc4e6651144bbce5517ccfbd9e42 + md5: 653b438353669616adf6e78ef62ef6fe + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + run_exports: {} + size: 773503 + timestamp: 1786085986536 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mkl-service-2.8.0-py314h3e0429d_0.conda + sha256: b3e279d095f9a244cb468fd90d9a9e53a3d6a29655dac746e4f08cfe146097e0 + md5: 3ad114ea01ade2d7a4f16ee7bcf9b15f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - mkl >=2026.1.0,<2027.0a0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/mkl-service?source=hash-mapping + run_exports: {} + size: 72541 + timestamp: 1785145637684 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + sha256: 5d46557214ed184381dafe835b7c94a474a1c3b307a08a250b1ea4779b44ffb3 + md5: ee6c0cd80a60961a1f48aa3e0b91f986 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: X11 AND BSD-3-Clause + purls: [] + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 911196 + timestamp: 1786355078102 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.66.0-py314h42812f9_1.conda + sha256: d8ca2096544bcff0aabc44468e3ad8c160222814704af77510bb97d00556c845 + md5: b2356f05812a7e3a724baa21617035f1 + depends: + - python + - llvmlite >=0.48.0,<0.49.0a0 + - numpy >=1.22.3,<2.5 + - libgcc >=14 + - _openmp_mutex >=4.5 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - numpy >=1.23,<3 + - python_abi 3.14.* *_cp314 + constrains: + - tbb >=2021.6.0 + - libopenblas !=0.3.6 + - cuda-version >=11.2 + - cudatoolkit >=11.2 + - scipy >=1.0 + - cuda-python >=11.6 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/numba?source=hash-mapping + run_exports: {} + size: 6182231 + timestamp: 1785940728959 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda + sha256: bc61ae892973751a6b0e6ecea57ed6d7053224bddcb007165d6ceb1d7344ad47 + md5: f49b5f950379e0b97c35ca97682f7c6a + depends: + - python + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - liblapack >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + run_exports: + weak: + - numpy >=1.23,<3 + size: 8928909 + timestamp: 1779169198391 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda + sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d + md5: 11b3379b191f63139e29c0d19dee24cd + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libpng >=1.6.50,<1.7.0a0 + - libstdcxx >=14 + - libtiff >=4.7.1,<4.8.0a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - openjpeg >=2.5.4,<3.0a0 + size: 355400 + timestamp: 1758489294972 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.13-hbde042b_0.conda + sha256: 21c4f6c7f41dc9bec2ea2f9c80440d9a4d45a6f2ac13243e658f10dcf1044146 + md5: 680608784722880fbfe1745067570b00 + depends: + - __glibc >=2.17,<3.0.a0 + - cyrus-sasl >=2.1.28,<3.0a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.6,<4.0a0 + license: OLDAP-2.8 + license_family: BSD + purls: [] + run_exports: + weak: + - openldap >=2.6.13,<2.7.0a0 + size: 786149 + timestamp: 1775741359582 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_1.conda + sha256: 012096056b97abf1f68c46b7146bd2cbd68c1be762340b4f5dad4fbbe99177bc + md5: c5955c27917ff2234def47f075e71e02 + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - openssl >=3.6.3,<4.0a0 + size: 3182423 + timestamp: 1785913583650 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pandoc-3.10.2-ha770c72_0.conda + sha256: 509d03571e126232f9eb38f1988ac9116f8c51df4a151071c4c6f3761d3fcb44 + md5: 80b992667dc547968afb633772891f71 + license: GPL-2.0-or-later + license_family: GPL + purls: [] + run_exports: {} + size: 22618408 + timestamp: 1786704311096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-h8b3dc9c_1.conda + sha256: 9ebb10a4eb3be51ae67d85c679f5a7a50cb040ed25c783e6331a225ea09991d4 + md5: 06f6113cf1ff4a54b65f87ead132a5f1 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 + size: 1218833 + timestamp: 1787294571916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.3.0-py314h8ec4b1a_0.conda + sha256: bcab128df8980514061a78b9c67f5004954048f584da20df8c5a78de9e3f5abb + md5: 233e62a8eb894b79b5c93f4f8dec4dcd + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libtiff >=4.7.1,<4.8.0a0 + - openjpeg >=2.5.4,<3.0a0 + - libxcb >=1.17.0,<2.0a0 + - zlib-ng >=2.3.3,<2.4.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - python_abi 3.14.* *_cp314 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - lcms2 >=2.19.1,<3.0a0 + - tk >=8.6.13,<8.7.0a0 + license: HPND + purls: + - pkg:pypi/pillow?source=hash-mapping + run_exports: {} + size: 1108174 + timestamp: 1782912080163 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_3.conda + sha256: 829d8288764282de5a9f7b9169acb75cc7dc0b6c3fe2535cfe87dea3436bbc5d + md5: 0ee5bb30034b081a1386c1e2c98ab0a7 + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 + size: 376704 + timestamp: 1786106621354 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314hfe1a184_1.conda + sha256: d4c4c9e1bcaeb38e4c4b6a17e8e0b25f8083e03d11813b872427bd47c9bfe1ca + md5: 1dadeb3cb86afd90e106395730cd87aa + depends: + - python + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + purls: + - pkg:pypi/psutil?source=hash-mapping + run_exports: {} + size: 231304 + timestamp: 1787417370367 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb03c661_1003.conda + sha256: afc3b27b2cbb0487c1d0e963f96e71181ecfb623a24fb393bb19ff974a6382a1 + md5: df2c27f36bdb0dde779f55b5df76a352 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 9115 + timestamp: 1786067714761 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyside6-6.11.2-py314h5d85b37_0.conda + sha256: ac013bb9f32a448468fad4269659fc772cf9eac7e5c9143c46bbe4f4a5a8922d + md5: 78780ea7feb32f4b6e0c9aae536081dd + depends: + - python + - qt6-main 6.11.2.* + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=15 + - libgl >=1.7.0,<2.0a0 + - libclang13 >=22.1.8 + - qt6-main >=6.11.2,<7.0a0 + - libxslt >=1.1.43,<2.0a0 + - libvulkan-loader >=1.4.357.0,<2.0a0 + - libegl >=1.7.0,<2.0a0 + - python_abi 3.14.* *_cp314 + - libxml2 + - libxml2-16 >=2.14.6 + - libopengl >=1.7.0,<2.0a0 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/pyside6?source=compressed-mapping + run_exports: {} + size: 13950298 + timestamp: 1787219457013 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pytensor-3.3.0-py314ha04e0d8_0.conda + sha256: 422882556b0136fd6939ae8be095e33b187712e642a485e0377a8332f33b23b5 + md5: 9ad1bfa1210ab7383edb3e88dfcc30a8 + depends: + - python + - pytensor-base ==3.3.0 np2py314h6477eea_0 + - gxx + - blas * mkl + - mkl-service + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 10732 + timestamp: 1786614356755 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pytensor-base-3.3.0-np2py314h6477eea_0.conda + sha256: d8bb7357a11263c6a8e7c89bafbb428ce7ba2e00703252553962a1985f5e7fda + md5: 139602b6549d6c1df664ca38324826f2 + depends: + - python + - setuptools >=59.0.0 + - scipy >=1,<2 + - numpy >=2.0 + - numba >=0.58,<=0.66.0 + - filelock >=3.15 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - python_abi 3.14.* *_cp314 + - numpy >=1.25,<3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pytensor?source=hash-mapping + run_exports: {} + size: 3221979 + timestamp: 1786614356755 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.7-h399a421_100_cp314.conda + build_number: 100 + sha256: ee59fa05898243b9a068476f4bed9461abef4487ebcdc094f569c4c47dc4a732 + md5: a9d6f626c591a56d7b7b36d2465f646d + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.8.1,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libuuid >=2.42.2,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.7,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 37028007 + timestamp: 1787154417160 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d + md5: 2035f68f96be30dc60a5dfd7452c7941 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + run_exports: {} + size: 202391 + timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.2.0-py312h8a5ba0d_0.conda + noarch: python + sha256: 9e8b94a2c9b4479cac80def117178a1658b089b9e5d4ee64408d2e4ff89fdaba + md5: ceffbc006d87e8f81e750cebd63fd8c4 + depends: + - python + - libstdcxx >=15 + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - zeromq >=4.3.5,<4.4.0a0 + - _python_abi3_support 1.* + - cpython >=3.12 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=compressed-mapping + run_exports: {} + size: 214050 + timestamp: 1787300896477 +- conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda + sha256: 776363493bad83308ba30bcb88c2552632581b143e8ee25b1982c8c743e73abc + md5: 353823361b1d27eb3960efb076dfcaf6 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: LicenseRef-Qhull + purls: [] + run_exports: + weak: + - qhull >=2020.2,<2020.3.0a0 + size: 552937 + timestamp: 1720813982144 +- conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.11.2-pl5321h9df5c37_0.conda + sha256: 00d9bc98d04aeeab6f698ca7fe9d666b157ab39b52cad1af0fa346522705668d + md5: 2ff98660281d1c6bfebda5bffa52cc89 + depends: + - libxcb + - xcb-util + - xcb-util-wm + - xcb-util-keysyms + - xcb-util-image + - xcb-util-renderutil + - xcb-util-cursor + - libgl-devel + - libegl-devel + - libgcc >=15 + - libstdcxx >=15 + - __glibc >=2.17,<3.0.a0 + - libglib >=2.88.3,<3.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libvulkan-loader >=1.4.357.0,<2.0a0 + - wayland >=1.26.0,<2.0a0 + - xorg-libx11 >=1.8.13,<2.0a0 + - libcups >=2.3.3,<2.4.0a0 + - alsa-lib >=1.2.16.1,<1.3.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libtiff >=4.7.2,<4.8.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + - dbus >=1.16.2,<2.0a0 + - libegl >=1.7.0,<2.0a0 + - xorg-libsm >=1.2.6,<2.0a0 + - xcb-util-wm >=0.4.2,<0.5.0a0 + - xorg-libice >=1.1.2,<2.0a0 + - xorg-libxxf86vm >=1.1.7,<2.0a0 + - double-conversion >=3.4.0,<3.5.0a0 + - icu >=78.3,<79.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - krb5 >=1.22.2,<1.23.0a0 + - xorg-libxcursor >=1.2.3,<2.0a0 + - pcre2 >=10.47,<10.48.0a0 + - openssl >=3.5.7,<4.0a0 + - xorg-libxcomposite >=0.4.7,<1.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - libpq >=18.6,<19.0a0 + - libxcb >=1.17.0,<2.0a0 + - xcb-util >=0.4.1,<0.5.0a0 + - xcb-util-keysyms >=0.4.1,<0.5.0a0 + - xcb-util-renderutil >=0.3.10,<0.4.0a0 + - xcb-util-image >=0.4.0,<0.5.0a0 + - libharfbuzz >=14.3.1 + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + - xorg-libxdamage >=1.1.6,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - libgl >=1.7.0,<2.0a0 + - xorg-libxrandr >=1.5.5,<2.0a0 + - libsqlite >=3.53.4,<4.0a0 + - xcb-util-cursor >=0.1.6,<0.2.0a0 + - libxkbcommon >=1.13.2,<2.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libdrm >=2.4.129,<2.5.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxtst >=1.2.5,<2.0a0 + constrains: + - qt ==6.11.2 + license: LGPL-3.0-only + license_family: LGPL + purls: [] + run_exports: + weak: + - qt6-main >=6.11.2,<7.0a0 + size: 60888449 + timestamp: 1787048975419 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda + sha256: 01b3fe073a66e321970d09e04b388708f8cbdca5cdfbfcb7c9eeb470ad10383d + md5: 69c01c781e7c8190bbdaf79e3848c5ca + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 348899 + timestamp: 1787033801506 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-2026.6.3-py314h7e8cd81_0.conda + sha256: 3425007379dc5b709b02699fa4329f1b82880a42f8dec40003cad7e7b6e2adac + md5: aefc39100f5d6c043d02a38c3b90ff47 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=compressed-mapping + run_exports: {} + size: 300155 + timestamp: 1787344359780 +- conda: https://conda.anaconda.org/conda-forge/linux-64/safetensors-0.8.0-py314h2e6c369_0.conda + sha256: 95c8621b6ce98ccb1c04549e8abcba58d69748ba98c0f132751356fa4be495f3 + md5: ab031a76083dab7ea346b6f68c3cd48f + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/safetensors?source=hash-mapping + run_exports: {} + size: 503263 + timestamp: 1781179688475 +- conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.18.0-py314hf07bd8e_0.conda + sha256: 85503102237f8515ab92319fc14609e894ac9e95e3a1398b0c49db1f9ee50877 + md5: 62c390c1f8f51240f1ebc7ba782669ad + depends: + - __glibc >=2.17,<3.0.a0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx >=14 + - numpy <2.7 + - numpy >=1.23,<3 + - numpy >=2.0.0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scipy?source=hash-mapping + run_exports: {} + size: 17260022 + timestamp: 1781912924009 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.52-py314h0f05182_0.conda + sha256: 0a3d82fb1650d364f8c2427d870a6c6684e02c9e5c4b0cccb6def83957f007fb + md5: c54cb6754823fe6710369511aab5c29c + depends: + - python + - greenlet !=0.4.17 + - typing-extensions >=4.6.0 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/sqlalchemy?source=compressed-mapping + run_exports: {} + size: 4047549 + timestamp: 1786535232010 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tbb-2023.0.0-hab88423_2.conda + sha256: 30cb9355c2fefc20ff1a3d6566b9714d5614086a2524c07721fc344eb20515ae + md5: 7073b15f9364ebc118998601ac6ca6a6 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libhwloc >=2.13.0,<2.13.1.0a0 + - libstdcxx >=14 + license: Apache-2.0 + license_family: APACHE + purls: [] + run_exports: {} + size: 182331 + timestamp: 1778673758649 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + build_number: 104 + sha256: a1a241d172c1ccab067ba245206dd048bc3c2d1b84504b53c9468e99adfc16a1 + md5: 676a2f9b1c4fcf57b70aa5c65f6c60d0 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - xorg-libx11 >=1.8.13,<2.0a0 + license: TCL + purls: [] + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3566806 + timestamp: 1787272857910 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.8-py314h5bd0f2a_0.conda + sha256: ebec0d90f99fa7bbe91eabab41ee77d3f36dbd58ec2f08aa4220fdd713610b6d + md5: faea84d2f2ccadf70cf9e55381d75b3e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=compressed-mapping + run_exports: {} + size: 923237 + timestamp: 1786226770518 +- conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py314h5bd0f2a_0.conda + sha256: ff1c1d7c23b91c9b0eb93a3e1380f4e2ac6c37ea2bba4f932a5484e9a55bba30 + md5: 494fdf358c152f9fdd0673c128c2f3dd + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/unicodedata2?source=hash-mapping + run_exports: {} + size: 409562 + timestamp: 1770909102180 +- conda: https://conda.anaconda.org/conda-forge/linux-64/watchfiles-1.2.0-py314h1bee95f_1.conda + sha256: 608e2de2bc61b3f271da82c30948074517c624c508ba5a7921ba742c0a4a013e + md5: 18dce090a0773324393c07048fdd6866 + depends: + - python + - anyio >=3.0.0 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/watchfiles?source=hash-mapping + run_exports: {} + size: 393293 + timestamp: 1781180266552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.26.0-h1964d1d_1.conda + sha256: a8f1333274382d23721d6f72483ece364631231f8ac3f74389951b1ff2820148 + md5: 47e3c5d0b1e968ee49efc7c3fa8ebc0c + depends: + - __glibc >=2.17,<3.0.a0 + - libexpat >=2.8.1,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - wayland >=1.26.0,<2.0a0 + size: 339462 + timestamp: 1786151675802 +- conda: https://conda.anaconda.org/conda-forge/linux-64/websockets-17.0.1-py314h518bba1_0.conda + sha256: c72d823ff108a0e0886ca5dc6a6d8c37effc5d02cf1c553138d607626a24f29f + md5: 399b4170029594ff7845022a519988fb + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/websockets?source=hash-mapping + run_exports: {} + size: 431439 + timestamp: 1785597284741 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-0.4.1-h4f16b4b_2.conda + sha256: ad8cab7e07e2af268449c2ce855cbb51f43f4664936eff679b1f3862e6e4b01d + md5: fdc27cb255a7a2cc73b7919a968b48f0 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libxcb >=1.17.0,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xcb-util >=0.4.1,<0.5.0a0 + size: 20772 + timestamp: 1750436796633 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-cursor-0.1.6-hb03c661_0.conda + sha256: c2be9cae786fdb2df7c2387d2db31b285cf90ab3bfabda8fa75a596c3d20fc67 + md5: 4d1fc190b99912ed557a8236e958c559 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libxcb >=1.13 + - libxcb >=1.17.0,<2.0a0 + - xcb-util-image >=0.4.0,<0.5.0a0 + - xcb-util-renderutil >=0.3.10,<0.4.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xcb-util-cursor >=0.1.6,<0.2.0a0 + size: 20829 + timestamp: 1763366954390 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-image-0.4.0-hb711507_2.conda + sha256: 94b12ff8b30260d9de4fd7a28cca12e028e572cbc504fd42aa2646ec4a5bded7 + md5: a0901183f08b6c7107aab109733a3c91 + depends: + - libgcc-ng >=12 + - libxcb >=1.16,<2.0.0a0 + - xcb-util >=0.4.1,<0.5.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xcb-util-image >=0.4.0,<0.5.0a0 + size: 24551 + timestamp: 1718880534789 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-keysyms-0.4.1-hb711507_0.conda + sha256: 546e3ee01e95a4c884b6401284bb22da449a2f4daf508d038fdfa0712fe4cc69 + md5: ad748ccca349aec3e91743e08b5e2b50 + depends: + - libgcc-ng >=12 + - libxcb >=1.16,<2.0.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xcb-util-keysyms >=0.4.1,<0.5.0a0 + size: 14314 + timestamp: 1718846569232 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-renderutil-0.3.10-hb711507_0.conda + sha256: 2d401dadc43855971ce008344a4b5bd804aca9487d8ebd83328592217daca3df + md5: 0e0cbe0564d03a99afd5fd7b362feecd + depends: + - libgcc-ng >=12 + - libxcb >=1.16,<2.0.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xcb-util-renderutil >=0.3.10,<0.4.0a0 + size: 16978 + timestamp: 1718848865819 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xcb-util-wm-0.4.2-hb711507_0.conda + sha256: 31d44f297ad87a1e6510895740325a635dd204556aa7e079194a0034cdd7e66a + md5: 608e0ef8256b81d04456e8d211eee3e8 + depends: + - libgcc-ng >=12 + - libxcb >=1.16,<2.0.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xcb-util-wm >=0.4.2,<0.5.0a0 + size: 51689 + timestamp: 1718844051451 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.48-h280c20c_0.conda + sha256: 3b04afd5d1a65d2d27ac2d49a63b01ab8bcd875776779ec63e337370ed38afdc + md5: b233b41be0bf210989d57160ed39b394 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 441670 + timestamp: 1782027360439 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-h280c20c_0.conda + sha256: 49b532d1df875c6749d9078b56a76f3f5db49a5abe0ca620b593ed474ef0ebf1 + md5: 85c9442aec283b4e464fa9ecc484a2f3 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libice >=1.1.2,<2.0a0 + size: 62517 + timestamp: 1786474410404 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-h0d788c3_1.conda + sha256: ef907caee0665cf3b0f775602cc50e388e3bade8ce22ecade0873ff26604b2fd + md5: aa7459ed9ad086ba11dda843d764b33d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libice >=1.1.2,<2.0a0 + - libuuid >=2.42.2,<3.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libsm >=1.2.6,<2.0a0 + size: 30739 + timestamp: 1786545374265 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_1.conda + sha256: 68053eebfa9f0d91666786c8fb5839d989aa9b869add92cb8815228bb2d7302c + md5: 8c282bbe4808a3cc80a5c98e9aec1cfc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libxcb >=1.17.0,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libx11 >=1.8.13,<2.0a0 + size: 839578 + timestamp: 1787087012372 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_2.conda + sha256: cbf891f6cc1a859347680af1c8562bc6b033bf182a2a3bb536016932be3206de + md5: f06ef439c280a5f90b8bf62355008dbc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxau >=1.0.12,<2.0a0 + size: 16419 + timestamp: 1786381001122 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.7-hb03c661_0.conda + sha256: 048c103000af9541c919deef03ae7c5e9c570ffb4024b42ecb58dbde402e373a + md5: f2ba4192d38b6cef2bb2c25029071d90 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libx11 >=1.8.12,<2.0a0 + - xorg-libxfixes >=6.0.2,<7.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxcomposite >=0.4.7,<1.0a0 + size: 14415 + timestamp: 1770044404696 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcursor-1.2.3-hb9d3cd8_0.conda + sha256: 832f538ade441b1eee863c8c91af9e69b356cd3e9e1350fff4fe36cc573fc91a + md5: 2ccd714aa2242315acaf0a67faea780b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - xorg-libx11 >=1.8.10,<2.0a0 + - xorg-libxfixes >=6.0.1,<7.0a0 + - xorg-libxrender >=0.9.11,<0.10.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxcursor >=1.2.3,<2.0a0 + size: 32533 + timestamp: 1730908305254 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdamage-1.1.6-hb9d3cd8_0.conda + sha256: 43b9772fd6582bf401846642c4635c47a9b0e36ca08116b3ec3df36ab96e0ec0 + md5: b5fcc7172d22516e1f965490e65e33a4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - xorg-libx11 >=1.8.10,<2.0a0 + - xorg-libxext >=1.3.6,<2.0a0 + - xorg-libxfixes >=6.0.1,<7.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxdamage >=1.1.6,<2.0a0 + size: 13217 + timestamp: 1727891438799 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_2.conda + sha256: c50a16c05ccd7fe7dd6d6cfb539f4e9a491d50f9ed7a5c902fec638f7d0d27be + md5: 2e66c929f3d879708335b6ea4557c838 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxdmcp >=1.1.5,<2.0a0 + size: 21120 + timestamp: 1786381006369 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-h7cc23a3_1.conda + sha256: aa9bbe8b278aacc194e280ff5037f9f9a1f2c5b33ed97de8e7f01cfbe90dda43 + md5: e5b6b28536b81b3f4cb20db4668a4642 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxext >=1.3.7,<2.0a0 + size: 53124 + timestamp: 1787100841900 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-h7cc23a3_1.conda + sha256: aec84f554fc897bf4085c7bc8b8f0740e4c224e13bca3cc51c93e7699d56f83a + md5: 09132e874fe0e1f5e4492b0b6b904b6e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxfixes >=6.0.2,<7.0a0 + size: 21440 + timestamp: 1787248059682 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.3-h7cc23a3_1.conda + sha256: a523d71344a2f640efe6fc42b88fc261d9cd389d4f9838a5d42dcdb120c2b0c8 + md5: a1412b2b1184dacda45f8476fef2cc25 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxfixes >=6.0.2,<7.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxi >=1.8.3,<2.0a0 + size: 49165 + timestamp: 1787257060460 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-h7cc23a3_1.conda + sha256: 05a7f25d7f7f5cd32b27a019233ece97167fd8ade255bc13a0e49e53387f4c30 + md5: 798a8c9d171859a022e1cb89e7d0eb10 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxrender >=0.9.12,<0.10.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxrandr >=1.5.5,<2.0a0 + size: 31106 + timestamp: 1787246614086 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb03c661_1.conda + sha256: 6901f91d398811e4ec89d7e20a69abac02a7bfebfaf073338b7ea3d1a99685b7 + md5: e470d224a7a5be1b1d021bded7abb536 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libx11 >=1.8.13,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxrender >=0.9.12,<0.10.0a0 + size: 34645 + timestamp: 1787100191192 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-h7cc23a3_4.conda + sha256: d66525e7b1c492aa179c6c55610fc8dfb0a9a62ea7d4fb9f904fa6af62127f61 + md5: 752a5ac9322e0fbbc24146c1ce3ae44e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - xorg-libx11 >=1.8.13,<2.0a0 + - xorg-libxext >=1.3.7,<2.0a0 + - xorg-libxi >=1.8.3,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxtst >=1.2.5,<2.0a0 + size: 35052 + timestamp: 1787360025506 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.7-hb03c661_0.conda + sha256: 64db17baaf36fa03ed8fae105e2e671a7383e22df4077486646f7dbf12842c9f + md5: 665d152b9c6e78da404086088077c844 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - xorg-libx11 >=1.8.12,<2.0a0 + - xorg-libxext >=1.3.6,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxxf86vm >=1.1.7,<2.0a0 + size: 18701 + timestamp: 1769434732453 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xorgproto-2025.1-h280c20c_1.conda + sha256: 051c6088bf2381840fcf8764737b829cc6c5f793718d2417d097d6e3b153eba9 + md5: 3b51576511038b50fdbd05245e22e4b1 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 594844 + timestamp: 1786114408394 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-hebe6cf0_3.conda + sha256: d164dfa75ecd538f6fd68765defcc06aa875bc697b9b215362d79a2a73125dd0 + md5: e741576fb8f89821ac7c1c537322a33d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 + size: 84936 + timestamp: 1787228426393 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h09e67af_11.conda + sha256: dc9f28dedcb5f35a127fad2d847674d2833369dd616d294e423b8997df31d8a8 + md5: 96b08867e21d4694fa5c2c226e6581b0 + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.22,<1.0.23.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + run_exports: + weak: + - zeromq >=4.3.5,<4.4.0a0 + size: 311184 + timestamp: 1779123989774 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hce19668_1.conda + sha256: 8b786bb4380fa69a718b08a400040b865bc9207eda337e0a1955717c3c3a9403 + md5: 1726acec19beeed1c764385cd8622405 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libstdcxx >=15 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - zlib-ng >=2.3.3,<2.4.0a0 + size: 123959 + timestamp: 1786736890973 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + sha256: 47d682b9f6d6ec9eb1a6e6c3e75ea6273e899e78fb7fc59f81d39745009fbc60 + md5: aa459086047c0e5e27023ab19f8cb86a + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 601301 + timestamp: 1786599621503 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_3.conda + sha256: 2a7204314663eeda5dec482a956f0e2eaf289bd5b9953eaaaad0e81aa64638f2 + md5: 3845f3d75991bae0fb90884662f4327c + depends: + - cpython + - python-gil + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 8144 + timestamp: 1784221492234 +- conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda + sha256: 1307719f0d8ee694fc923579a39c0621c23fdaa14ccdf9278a5aac5665ac58e9 + md5: 74ac5069774cdbc53910ec4d631a3999 + depends: + - pygments + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/accessible-pygments?source=hash-mapping + run_exports: {} + size: 1326096 + timestamp: 1734956217254 +- conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda + sha256: 6c4456a138919dae9edd3ac1a74b6fbe5fd66c05675f54df2f8ab8c8d0cc6cea + md5: 1fd9696649f65fd6611fcdb4ffec738a + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/alabaster?source=hash-mapping + run_exports: {} + size: 18684 + timestamp: 1733750512696 +- conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.14.2-pyhcf101f3_0.conda + sha256: e36998c5e860e26b22e5dbcd5726dd0c4eabad949c84d383cad8512757bbf6a1 + md5: fb568fbae6908ba86a090a85a089d11f + depends: + - exceptiongroup >=1.0.2 + - idna >=2.8 + - python >=3.10 + - typing_extensions >=4.5 + - python + constrains: + - trio >=0.32.0 + - uvloop >=0.22.1 + - winloop >=0.2.3 + license: MIT + license_family: MIT + purls: + - pkg:pypi/anyio?source=hash-mapping + run_exports: {} + size: 164465 + timestamp: 1783889660383 +- conda: https://conda.anaconda.org/conda-forge/noarch/appnope-1.0.0-pyhcf101f3_0.conda + sha256: 52bc705ba773214cb2f8f884ee0128d007fa7dfdcf19218c910465381b91cd6e + md5: 56d53a5e9740367f5f8cf83f995263c2 + depends: + - python >=3.10 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/appnope?source=compressed-mapping + run_exports: {} + size: 12232 + timestamp: 1787337124448 +- 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 + run_exports: {} + size: 18715 + timestamp: 1749017288144 +- 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 + run_exports: {} + size: 113854 + timestamp: 1760831179410 +- conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.2-pyhd8ed1ab_0.conda + sha256: fbbd8ce60cbd5c16f3fe559eb644551f94285caff30985ea961ff851c1cf25ac + md5: 89d495168582cb00428dad699d149624 + depends: + - python >=3.10 + constrains: + - astroid >=2,<5 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/asttokens?source=hash-mapping + run_exports: {} + size: 34639 + timestamp: 1783975742052 +- conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + sha256: ea8486637cfb89dc26dc9559921640cd1d5fd37e5e02c33d85c94572139f2efe + md5: b85e84cb64c762569cc1a760c2327e0a + depends: + - python >=3.10 + - typing_extensions >=4.0.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/async-lru?source=hash-mapping + run_exports: {} + size: 22949 + timestamp: 1773926359134 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab + md5: c6b0543676ecb1fb2d7643941fe375f2 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/attrs?source=hash-mapping + run_exports: {} + size: 64927 + timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + sha256: a14a9ad02101aab25570543a59c5193043b73dc311a25650134ed9e6cb691770 + md5: f1976ce927373500cc19d3c0b2c85177 + depends: + - python >=3.10 + - python + constrains: + - pytz >=2015.7 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/babel?source=hash-mapping + run_exports: {} + size: 7684321 + timestamp: 1772555330347 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.7.0-py314h680f03e_0.conda + noarch: generic + sha256: 19514d89d1e725e44b0650d31a4d43da8e070e4e93e4131e3b16bd139404f2b2 + md5: 92adf685875ab717f68ad4172ef6de27 + depends: + - python >=3.14 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: [] + run_exports: {} + size: 7541 + timestamp: 1786861415851 +- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.15.0-pyha770c72_0.conda + sha256: aed4b9dcf68ec2a75e5645fed14d77fd884d38d2e52bfa6ef4b278d90cd88781 + md5: 3b261da3fe9b4168738712832410b022 + depends: + - python >=3.10 + - soupsieve >=1.2 + - typing-extensions + license: MIT + license_family: MIT + purls: + - pkg:pypi/beautifulsoup4?source=hash-mapping + run_exports: {} + size: 92704 + timestamp: 1780853175566 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.4.0-pyhcf101f3_0.conda + sha256: 0c786f3e571bd58ac73d730d06314716663884d848ae320de0b438fae5e0bea9 + md5: 93009c29cdd6f2500468f2502fff9209 + depends: + - python >=3.10 + - webencodings + - python + constrains: + - tinycss2 >=1.1.0,<1.5 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/bleach?source=hash-mapping + run_exports: {} + size: 142246 + timestamp: 1780675823953 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.4.0-hac0b51c_0.conda + sha256: ede77e412304cd080e23967352a7904932207d0167ecdccd6a9e210530942be6 + md5: 5f710eab1f3c4e773c75686f5e8e6481 + depends: + - bleach ==6.4.0 pyhcf101f3_0 + - tinycss2 + license: Apache-2.0 AND MIT + purls: [] + run_exports: {} + size: 4406 + timestamp: 1780675823953 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-h4c7d964_0.conda + sha256: 95e8e74062a5fe5f870ac8c90302b6e89945165fdaed7810606e84ddee6aac12 + md5: e27d2ac27b096dc51fedfcf775a53f9b + depends: + - __win + license: ISC + purls: [] + run_exports: {} + size: 132136 + timestamp: 1784754918886 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda + sha256: 0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6 + md5: 0f51e2391ade309db462a55611263e9c + depends: + - __unix + license: ISC + purls: [] + run_exports: {} + size: 131780 + timestamp: 1784754889428 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_2.conda + noarch: python + sha256: 0d00dd61cb91b1bd1536600c64c9db4f94f3c699fec42864d0a2f4bc2ad8c3e8 + md5: 1990eb3f49022846fbc7fc9624a0ee43 + depends: + - cached_property >=1.5.2,<1.5.3.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 6836 + timestamp: 1783242914545 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_2.conda + sha256: b1808a7811b5688d045b204425bb7ee824b340b40025b4ad0a39b4db1f4f1c98 + md5: f71e6840332854fd2eac6c3229768a9c + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/cached-property?source=hash-mapping + run_exports: {} + size: 14752 + timestamp: 1783242913845 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.7.22-pyhd8ed1ab_0.conda + sha256: fb167de4388e64e52aa3907ed099afab944c1fa6e5f74b281a312dae1bcf7f3b + md5: 37e13edbe3b48f1095a9d085ef9cd83b + depends: + - python >=3.10 + license: ISC + purls: + - pkg:pypi/certifi?source=hash-mapping + run_exports: {} + size: 137015 + timestamp: 1784717699092 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.5.1-pyhd8ed1ab_0.conda + sha256: cb60ef3e0631c8bacb4f7057196dee4496091a22baa3bb4b9bccb12c7e1c921b + md5: e0ac3accc64e23e40969d660e5f58ac8 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/charset-normalizer?source=compressed-mapping + run_exports: {} + size: 64487 + timestamp: 1786835648298 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.2-pyh6dadd2b_0.conda + sha256: 5b5c96afdd801dd9c3b78ebc2cd9a9f3ce34186257415d394dde1aa8468aa3c0 + md5: 8a0d65027e25e367f9f1754f0604e8de + depends: + - __win + - colorama + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/click?source=hash-mapping + run_exports: {} + size: 106227 + timestamp: 1783085395110 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.2-pyhc90fa1f_0.conda + sha256: ccc4787f511964f9a1f2d2d2859c91c5d571fb60f7f09d4c4e092c9b7a94e671 + md5: 2c4bd6aeb90bb157456841c3270a0d92 + depends: + - __unix + - python + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/click?source=hash-mapping + run_exports: {} + size: 107155 + timestamp: 1783085363526 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama?source=hash-mapping + run_exports: {} + 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 + run_exports: {} + size: 14690 + timestamp: 1753453984907 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_osx-arm64-22.1.8-hb8825d9_2.conda + sha256: 016121f654e8052edf0e9912ab2f430c2d6ac93adc8cfd484318de6a656cd0c9 + md5: e603f604aa1e281db38ff849cc4e4c5d + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 10565200 + timestamp: 1787293602816 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-22.1.8-hce30654_2.conda + sha256: 35a0429b875ff8252b173e4c0a3b028f58ea837da56b04e052ffc2c68c253633 + md5: 79874270cd835b658d889f4cd054677b + depends: + - compiler-rt22_osx-arm64 22.1.8 hb8825d9_2 + constrains: + - clang 22.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 16768 + timestamp: 1787293624614 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.7-py314hd8ed1ab_100.conda + noarch: generic + sha256: 2a58aa937a36623e97d23fe595f26f56e0bfe9ecbac7418699f8b5744de15de1 + md5: 43ee8b10fa6955115c1969d04caa49a3 + depends: + - python >=3.14,<3.15.0a0 + - python_abi * *_cp314 + license: Python-2.0 + purls: [] + run_exports: {} + size: 50365 + timestamp: 1787153603657 +- conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda + sha256: bb47aec5338695ff8efbddbc669064a3b10fe34ad881fb8ad5d64fbfa6910ed1 + md5: 4c2a8fef270f6c69591889b93f9f55c1 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/cycler?source=hash-mapping + run_exports: {} + size: 14778 + timestamp: 1764466758386 +- conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + sha256: 9717a059677553562a8f38ff07f3b9f61727bd614f505658b0a5ecbcf8df89be + md5: 961b3a227b437d82ad7054484cfa71b2 + depends: + - python >=3.6 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/defusedxml?source=hash-mapping + run_exports: {} + size: 24062 + timestamp: 1615232388757 +- conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.22.4-pyhd8ed1ab_0.conda + sha256: 0d605569a77350fb681f9ed8d357cc71649b59a304099dc9d09fbeec5e84a65e + md5: d6bd3cd217e62bbd7efe67ff224cd667 + depends: + - python >=3.10 + license: CC-PDDC AND BSD-3-Clause AND BSD-2-Clause AND ZPL-2.1 + purls: + - pkg:pypi/docutils?source=hash-mapping + run_exports: {} + size: 438002 + timestamp: 1766092633160 +- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 + md5: 8e662bd460bda79b1ea39194e3c4c9ab + depends: + - python >=3.10 + - typing_extensions >=4.6.0 + license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup?source=hash-mapping + run_exports: {} + 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 + run_exports: {} + size: 30753 + timestamp: 1756729456476 +- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.32.4-pyhd8ed1ab_0.conda + sha256: c2c2527101fea8d2fbae3883d3328a4cd225e8fc3f133b49504acb7a8cecf6fe + md5: 0171dc5d54fdbb3f6e55f285f805e0fe + depends: + - python >=3.10 + license: Unlicense + purls: + - pkg:pypi/filelock?source=compressed-mapping + run_exports: {} + size: 78622 + timestamp: 1787521663311 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 + sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b + md5: 0c96522c6bdaed4b1566d11387caaf45 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 397370 + timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 + sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c + md5: 34893075a5c9e55cdafac56607368fc6 + license: OFL-1.1 + license_family: Other + purls: [] + run_exports: {} + size: 96530 + timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 + sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 + md5: 4d59c254e01d9cde7957100457e2d5fb + license: OFL-1.1 + license_family: Other + purls: [] + run_exports: {} + size: 700814 + timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda + sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 + md5: 49023d73832ef61042f6a237cb2687e7 + license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 + license_family: Other + purls: [] + run_exports: {} + size: 1620504 + timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 + sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 + md5: fee5683a3f04bd15cbd8318b096a27ab + depends: + - fonts-conda-forge + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 3667 + timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda + sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 + md5: a7970cd949a077b7cb9696379d338681 + depends: + - font-ttf-ubuntu + - font-ttf-inconsolata + - font-ttf-dejavu-sans-mono + - font-ttf-source-code-pro + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 4059 + timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonttools-4.63.0-pyh7db6752_0.conda + sha256: c9752235f1ff7061d834e5e4a3d0adf71ebeeff2b3fad82dab607edce7f70c91 + md5: 0509ee74d95e5b98eb6fe2a47760e399 + depends: + - brotli + - munkres + - python >=3.10 + - unicodedata2 >=15.1.0 + track_features: + - fonttools_no_compile + license: MIT + license_family: MIT + purls: + - pkg:pypi/fonttools?source=hash-mapping + run_exports: {} + size: 846038 + timestamp: 1778770337113 +- 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 + run_exports: {} + size: 16705 + timestamp: 1733327494780 +- conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + sha256: 96cac6573fd35ae151f4d6979bab6fbc90cb6b1fb99054ba19eb075da9822fcb + md5: b8993c19b0c32a2f7b66cbb58ca27069 + depends: + - python >=3.10 + - typing_extensions + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h11?source=hash-mapping + run_exports: {} + size: 39069 + timestamp: 1767729720872 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.4.1-pyhcf101f3_0.conda + sha256: 307dd6ec90140c3cf4171071b0e5e870abec314f4565c1edd5bc433e942cdcc0 + md5: e652ac7756069c456d0da2a922cd7df5 + depends: + - python >=3.10 + - hyperframe >=6.1,<7 + - hpack >=4.2,<5 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h2?source=hash-mapping + run_exports: {} + size: 100789 + timestamp: 1785796355216 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda + sha256: fdcea5d7cb314485d3907192ef024c704311548c5b0cbeb390cd1951051e29d2 + md5: b395909221b9bd1df066e5930e18855b + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hpack?source=hash-mapping + run_exports: {} + size: 32884 + timestamp: 1782283986153 +- conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + sha256: 04d49cb3c42714ce533a8553986e1642d0549a05dc5cc48e0d43ff5be6679a5b + md5: 4f14640d58e2cc0aa0819d9d8ba125bb + depends: + - python >=3.9 + - h11 >=0.16 + - h2 >=3,<5 + - sniffio 1.* + - anyio >=4.0,<5.0 + - certifi + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/httpcore?source=hash-mapping + run_exports: {} + size: 49483 + timestamp: 1745602916758 +- conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + sha256: cd0f1de3697b252df95f98383e9edb1d00386bfdd03fdf607fa42fe5fcb09950 + md5: d6989ead454181f4f9bc987d3dc4e285 + depends: + - anyio + - certifi + - httpcore 1.* + - idna + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/httpx?source=hash-mapping + run_exports: {} + size: 63082 + timestamp: 1733663449209 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hyperframe?source=hash-mapping + run_exports: {} + size: 17397 + timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.19-pyhcf101f3_0.conda + sha256: 1c35a59c1545ad0fdaddf1fbde7bcfa6ef41a8d68c3a2b0b4a291be00676163e + md5: a39ae05027e9b707742e41b30d296b75 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/idna?source=compressed-mapping + run_exports: {} + size: 177433 + timestamp: 1787059857580 +- conda: https://conda.anaconda.org/conda-forge/noarch/imagesize-2.0.0-pyhd8ed1ab_0.conda + sha256: 5a047f9eac290e679b4e6f6f4cbfcc5acdfbf031a4f06824d4ddb590cdbb850b + md5: 92617c2ba2847cca7a6ed813b6f4ab79 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/imagesize?source=hash-mapping + run_exports: {} + size: 15729 + timestamp: 1773752188889 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda + sha256: 43e2a5497cad1598ff88a3e69f69bc88b7b8f141fa63c60eab5db296317318b8 + md5: ffc17e785d64e12fc311af9184221839 + depends: + - python >=3.10 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/importlib-metadata?source=hash-mapping + run_exports: {} + size: 34766 + timestamp: 1779714582554 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.3.0-pyh01cf8df_0.conda + sha256: 994d3cb6b9b88a6533f567c50d20f2f6edc40ae3540ce2ee9629492182ab3403 + md5: a1ddab91145f7f06eee769d2f3ac69cd + depends: + - appnope + - __osx + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.9.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio2 >=1.7.0 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + run_exports: {} + size: 137725 + timestamp: 1781101860049 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.3.0-pyh6dadd2b_0.conda + sha256: e3ff0b3d5db5c31830030406f50ac2c9a5c31b86f1c2cef87a6042f0a4c77eb7 + md5: dd5c51d5c42381ba4a2e0ce32e02ba17 + depends: + - __win + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.9.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio2 >=1.7.0 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + run_exports: {} + size: 138046 + timestamp: 1781101760172 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.3.0-pyha191276_0.conda + sha256: 305ad9226363ff5f259c404dd9a7508183a2e150739b2adc43db7d817234da66 + md5: 2b47a10e4d98334f8171ff60aea05ff3 + depends: + - __linux + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.9.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio2 >=1.7.0 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + run_exports: {} + size: 138635 + timestamp: 1781101665847 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.16.1-pyh53cf698_0.conda + sha256: 8470648b5e790d1881c09c02068d53e1bf0126f020db02a6dc2e73400cf1eeeb + md5: 23564ed27c9c7714905be96ac5786500 + depends: + - __unix + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.2 + - matplotlib-inline >=0.1.6 + - prompt-toolkit >=3.0.41,<3.1.0 + - psutil >=7 + - pygments >=2.14.0 + - python >=3.11 + - stack_data >=0.6.0 + - traitlets >=5.13.0 + - typing_extensions >=4.6 + - pexpect >4.6 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython?source=hash-mapping + run_exports: {} + size: 716078 + timestamp: 1785754203352 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.16.1-pyhe2676ad_0.conda + sha256: 2a0cd24e5c0e1eb8b7baf06346906673f6b8abea151ce302d7d978a3c416aeec + md5: d7c95d926befcfa22bee69bb1980e2ce + depends: + - __win + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.2 + - matplotlib-inline >=0.1.6 + - prompt-toolkit >=3.0.41,<3.1.0 + - psutil >=7 + - pygments >=2.14.0 + - python >=3.11 + - stack_data >=0.6.0 + - traitlets >=5.13.0 + - typing_extensions >=4.6 + - colorama >=0.4.4 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython?source=hash-mapping + run_exports: {} + size: 715162 + timestamp: 1785754256301 +- 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 + run_exports: {} + size: 13993 + timestamp: 1737123723464 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.1.9-pyhd8ed1ab_0.conda + sha256: c391fe12c24fce4f8380f44ebdfb62a5ecdbf0ee168e7db7ea9baf3527eec003 + md5: 1efaf89bb5d9a6ff2ce5f84d25678f53 + depends: + - comm >=0.1.3 + - ipython >=6.1.0 + - jupyterlab_widgets >=3.0.17,<3.1.0 + - python >=3.10 + - traitlets >=4.3.1 + - widgetsnbextension >=4.0.16,<4.1.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipywidgets?source=compressed-mapping + run_exports: {} + size: 115707 + timestamp: 1787052940568 +- 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 + run_exports: {} + size: 19832 + timestamp: 1733493720346 +- conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.20.0-pyhcf101f3_0.conda + sha256: 744143551c1c7b528b82533fb641b9d7db20b2203abc4c2635c387fa6c089fc3 + md5: c2b3d37aa1411031126036ee76a8a861 + depends: + - python >=3.10 + - parso >=0.8.6,<0.9.0 + - python + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/jedi?source=hash-mapping + run_exports: {} + size: 2715215 + timestamp: 1782251948616 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b + md5: 04558c96691bed63104678757beb4f8d + depends: + - markupsafe >=2.0 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jinja2?source=hash-mapping + run_exports: {} + size: 120685 + timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.15.0-pyhd8ed1ab_0.conda + sha256: 637400a4174880463985c7a5b6e3e0bea0aa9d0892a6c06a3a8aa2cf1208c35a + md5: 761a4a6b9cba303c66a97ca642447171 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/json5?source=hash-mapping + run_exports: {} + size: 39373 + timestamp: 1781926894833 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + sha256: a3d10301b6ff399ba1f3d39e443664804a3d28315a4fb81e745b6817845f70ae + md5: 89bf346df77603055d3c8fe5811691e6 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jsonpointer?source=hash-mapping + run_exports: {} + size: 14190 + timestamp: 1774311356147 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_1.conda + sha256: 328756a4555941d57af4a5f553e5d8598e9f3b37db028f557e30f9f0b3086db6 + md5: 204b5ca91eba7738790ecc333facbbbe + depends: + - attrs >=22.2.0 + - jsonschema-specifications >=2023.3.6 + - python >=3.10 + - referencing >=0.28.4 + - rpds-py >=0.25.0 + - python + license: MIT + purls: + - pkg:pypi/jsonschema?source=compressed-mapping + run_exports: {} + size: 82084 + timestamp: 1787579299493 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 + md5: 439cd0f567d697b20a8f45cb70a1005a + depends: + - python >=3.10 + - referencing >=0.31.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/jsonschema-specifications?source=hash-mapping + run_exports: {} + size: 19236 + timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_1.conda + sha256: 1b8ed25276ceae973e21d269fbe11f08d0b5f73c7ac9584e2d6a9dd763b8707a + md5: ae36c895b9e25a127d2acbdbaa87e301 + depends: + - jsonschema >=4.26.0,<4.26.1.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 + purls: [] + run_exports: {} + size: 4809 + timestamp: 1787579299493 +- 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 + run_exports: {} + size: 8891 + timestamp: 1733818677113 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-builder-1.2.2-pyhcf101f3_0.conda + sha256: 46777dd25ae623f960ec9ed9eae44cc7f96f371f3bc96f85d3ebf95737bd4e88 + md5: 9672806e67ea8b09a61408597a418e20 + depends: + - jupyter_core + - python >=3.10 + - tomli + - traitlets + - python + constrains: + - nodejs >=22 + license: BSD-3-Clause AND MIT AND ISC + purls: + - pkg:pypi/jupyter-builder?source=compressed-mapping + run_exports: {} + size: 862197 + timestamp: 1786385602872 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-cache-1.0.1-pyhff2d567_0.conda + sha256: 054d397dd45ed08bffb0976702e553dfb0d0b0a477da9cff36e2ea702e928f48 + md5: b0ee650829b8974202a7abe7f8b81e5a + depends: + - attrs + - click + - importlib-metadata + - nbclient >=0.2 + - nbformat + - python >=3.9 + - pyyaml + - sqlalchemy >=1.3.12,<3 + - tabulate + license: MIT + license_family: MIT + purls: + - pkg:pypi/jupyter-cache?source=hash-mapping + run_exports: {} + size: 31236 + timestamp: 1731777189586 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + sha256: 3766e2ae59641c172cec8a821528bfa6bf9543ffaaeb8b358bfd5259dcf18e4e + md5: 0c3b465ceee138b9c39279cc02e5c4a0 + 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 + run_exports: {} + size: 61633 + timestamp: 1775136333147 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-sphinx-0.5.3-pyha770c72_5.conda + sha256: f001c315740c26ffb5591db4cf0131a4de4017804049f8817c11ed3dae18925d + md5: 868d6d1da5fefbd902f6f2a74a02ff7e + depends: + - ipykernel >=4.5.1 + - ipython + - ipywidgets >=7.0.0 + - nbconvert >=5.5 + - nbformat + - python >=3.9 + - sphinx >=7 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-sphinx?source=hash-mapping + run_exports: {} + size: 24112 + timestamp: 1734429364515 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.9.1-pyhcf101f3_0.conda + sha256: 48b18974cc93b2c0d2681563237034e521f51d1878f0bbc6a5a67ca31b1608a6 + md5: 49440e66df843bee2273937e8032ec43 + depends: + - jupyter_core >=5.1 + - python >=3.10 + - python-dateutil >=2.8.2 + - pyzmq >=25.0 + - tornado >=6.4.1 + - traitlets >=5.3 + - typing_extensions >=4.13.0 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-client?source=hash-mapping + run_exports: {} + size: 117954 + timestamp: 1781019994076 +- 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 + run_exports: {} + size: 26874 + timestamp: 1733818130068 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + sha256: ed709a6c25b731e01563521ef338b93986cd14b5bc17f35e9382000864872ccc + md5: a8db462b01221e9f5135be466faeb3e0 + depends: + - __win + - pywin32 + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-core?source=hash-mapping + run_exports: {} + size: 64679 + timestamp: 1760643889625 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a + md5: b38fe4e78ee75def7e599843ef4c1ab0 + depends: + - __unix + - python + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-core?source=hash-mapping + run_exports: {} + size: 65503 + timestamp: 1760643864586 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + sha256: c7edb5682c6316a95ad781dccb1b6589cd2ec0bf94f23c21152974eb0363b5d7 + md5: bf42ee94c750c0b2e7e998b79ac299ea + depends: + - jsonschema-with-format-nongpl >=4.18.0 + - packaging + - python >=3.10 + - 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 + run_exports: {} + size: 24002 + timestamp: 1776861872237 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.20.0-pyhcf101f3_0.conda + sha256: 3e8759fdc404f149e7e722e0af472044a0ef9e70d0a3a7690ddcfe1232a0e868 + md5: b2ddb0e13b5600070c4019c4db8a78e6 + 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 + run_exports: {} + size: 363068 + timestamp: 1781713810089 +- 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 + run_exports: {} + size: 22052 + timestamp: 1768574057200 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.6.3-pyhd8ed1ab_0.conda + sha256: dabfff705b000188a9f67c9af68bb607cdb2e46fd7c6283307a502994c2af46f + md5: e5527f195a1a1925b9207e9d47752480 + depends: + - async-lru >=1.0.0 + - httpx >=0.25.0,<1 + - ipykernel >=6.5.0,!=6.30.0 + - jinja2 >=3.0.3 + - jupyter-builder >=1.0.2 + - jupyter-lsp >=2.0.0 + - jupyter_core + - jupyter_server >=2.19.0,<3 + - jupyterlab_server >=2.28.0,<3 + - notebook-shim >=0.2 + - packaging >=23.2 + - python >=3.10 + - tomli >=1.2.2 + - tornado >=6.2.0 + - traitlets + - typing_extensions >=4.4.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab?source=compressed-mapping + run_exports: {} + size: 13178193 + timestamp: 1786398793317 +- 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 + run_exports: {} + 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 + run_exports: {} + size: 51621 + timestamp: 1761145478692 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.17-pyhcf101f3_0.conda + sha256: 697c4a5b4771e8fbd5a9bbb614899982c7e586eafaf123c210f9d1794436f00a + md5: 1fb3f0d175d6e92f56139fb46a17aa2d + depends: + - python >=3.10 + - python + constrains: + - jupyterlab >=4,<5 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-widgets?source=compressed-mapping + run_exports: {} + size: 219589 + timestamp: 1787045328396 +- conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + sha256: 41557eeadf641de6aeae49486cef30d02a6912d8da98585d687894afd65b356a + md5: 86d9cba083cd041bfbf242a01a7a1999 + constrains: + - sysroot_linux-64 ==2.28 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + purls: [] + run_exports: {} + size: 1278712 + timestamp: 1765578681495 +- 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=hash-mapping + run_exports: {} + size: 94312 + timestamp: 1761596921009 +- conda: https://conda.anaconda.org/conda-forge/noarch/latexcodec-2.0.1-pyh9f0ad1d_0.tar.bz2 + sha256: 5210d31c8f2402dd1ad1b3edcf7a53292b9da5de20cd14d9c243dbf9278b1c4f + md5: 8d67904973263afd2985ba56aa2d6bb4 + depends: + - python + - six + license: MIT + license_family: MIT + purls: + - pkg:pypi/latexcodec?source=hash-mapping + run_exports: {} + size: 18212 + timestamp: 1592937373647 +- conda: https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-22.1.8-h707e725_0.conda + sha256: 0b9853ca0d29729488519ab5c61401b1ade22b15841dae8bf299e6980fe1c964 + md5: 2306682595f6d2a5e67fab177427e139 + depends: + - __unix + constrains: + - clangxx >=19 + - gxx_osx-64 >=14 + - libcxx-devel 22.1.8 + - gxx_osx-arm64 >=14 + - gxx_linux-64 >=14 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + run_exports: {} + size: 1149924 + timestamp: 1781670214284 +- conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-16.2.0-he3ce08f_104.conda + sha256: 5365adce4b7564ba3773d037d84070d68ec1269d4b35f3ab92536ee1087a99a5 + md5: f2cf63d33e7be7f7722479fb30d9e332 + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 3095149 + timestamp: 1787618545895 +- conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_win-64-16.1.0-hecf7705_103.conda + sha256: 104d0b85ea2caaa6bb1dd10f0eedf07646655e22d0087994b12251b786788dbc + md5: 054e1d6be93f2803ce5a4e957f8f107a + depends: + - m2-conda-epoch + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: {} + size: 2418775 + timestamp: 1787332962237 +- conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-16.2.0-h86e191b_104.conda + sha256: 435877f29650022730300859dec5c0dee162d10536e1b6fd01cf93ca33a71fde + md5: 83cdebeadbdacc2692cb4797d188c77a + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 22447939 + timestamp: 1787618628584 +- conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_win-64-16.1.0-hc76ffd0_103.conda + sha256: e6a43af00adc3256fb369c58b8bc7d3b45e6e681365601389a28c65b2152bb84 + md5: 5f33ef8965affac2c15a962911c933dd + depends: + - m2-conda-epoch + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: {} + size: 13130838 + timestamp: 1787332984486 +- conda: https://conda.anaconda.org/conda-forge/noarch/m2w64-sysroot_win-64-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + sha256: fb0ffe6b3c25189038c29abbd1fac2522d87fe2775a09e5f5088e5542dc3309b + md5: 9676d2a30fa3ffa4e5350041d0993758 + depends: + - m2-conda-epoch + - mingw-w64-ucrt-x86_64-crt-git 12.0.0.r4.gg4f2fc60ca hd8ed1ab_10 + - mingw-w64-ucrt-x86_64-headers-git 12.0.0.r4.gg4f2fc60ca hd8ed1ab_10 + - mingw-w64-ucrt-x86_64-windows-default-manifest + - mingw-w64-ucrt-x86_64-winpthreads-git 12.0.0.r4.gg4f2fc60ca hd8ed1ab_10 + - ucrt + purls: [] + run_exports: + strong: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + size: 8421 + timestamp: 1759768559974 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda + sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f + md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 + depends: + - mdurl >=0.1,<1 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/markdown-it-py?source=hash-mapping + run_exports: {} + size: 69017 + timestamp: 1778169663339 +- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.2-pyhd8ed1ab_0.conda + sha256: 35b43d7343f74452307fd018a1cca92b8f68961ff8e2ab6a81ce0a703c9a3764 + md5: 9acc1c385be401d533ff70ef5b50dae6 + depends: + - python >=3.10 + - traitlets + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/matplotlib-inline?source=hash-mapping + run_exports: {} + size: 15725 + timestamp: 1778264403247 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdit-py-plugins-0.6.1-pyhd8ed1ab_0.conda + sha256: 49db23cbfb1c1d414a14d7540195208b994ebd747beba0f15c903f3a0a2dc446 + md5: ad6821df7a98510117db06e9a833281f + depends: + - markdown-it-py >=2.0.0,<5.0.0 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mdit-py-plugins?source=hash-mapping + run_exports: {} + size: 50460 + timestamp: 1778692223625 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda + sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 + md5: 592132998493b3ff25fd7479396e8351 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mdurl?source=hash-mapping + run_exports: {} + size: 14465 + timestamp: 1733255681319 +- conda: https://conda.anaconda.org/conda-forge/noarch/mingw-w64-ucrt-x86_64-crt-git-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + sha256: de3e42149b498c16bfb485b7729f4ca0fe392be576a2a10ff702d661799b1df3 + md5: 44ffa6d68699ec9321f6d48d75bdc726 + depends: + - m2-conda-epoch + - mingw-w64-ucrt-x86_64-headers-git 12.0.0.r4.gg4f2fc60ca hd8ed1ab_10 + constrains: + - mingw-w64-ucrt-x86_64-winpthreads-git 12.0.0.r4.gg4f2fc60ca.* + license: ZPL-2.1 + purls: [] + run_exports: {} + size: 5663635 + timestamp: 1759768458961 +- conda: https://conda.anaconda.org/conda-forge/noarch/mingw-w64-ucrt-x86_64-headers-git-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + sha256: 1add86481f35163215e7076e6f06f22aa9f1f9345a5fff5cb07bc846c13fbec7 + md5: cab7b807024204893ef5bb1860d91408 + depends: + - m2-conda-epoch + constrains: + - mingw-w64-ucrt-x86_64-crt-git 12.0.0.r4.gg4f2fc60ca.* + - mingw-w64-ucrt-x86_64-winpthreads-git 12.0.0.r4.gg4f2fc60ca.* + license: ZPL-2.1 AND LGPL-2.1-or-later + purls: [] + run_exports: {} + size: 7089846 + timestamp: 1759768412123 +- conda: https://conda.anaconda.org/conda-forge/noarch/mingw-w64-ucrt-x86_64-windows-default-manifest-6.4-he206cdd_7.conda + sha256: 5b0df4e0ba8487ffd59f60c34c5dbb9e001ecd2c5d2c66ba88eada40bfa3ecb8 + md5: 1d6b5c96d7e3cce773519d7d1a4482f0 + depends: + - __win + constrains: + - m2w64-sysroot_win-64 >=12.0.0.r0 + license: FSFAP + purls: [] + run_exports: {} + size: 7412 + timestamp: 1717486007140 +- conda: https://conda.anaconda.org/conda-forge/noarch/mingw-w64-ucrt-x86_64-winpthreads-git-12.0.0.r4.gg4f2fc60ca-hd8ed1ab_10.conda + sha256: 828abb111286940473c4c665fc8ab300d28920f5af83b32295e8bf2256a8f342 + md5: ba0eeff6a5c62b83c771bb392e22dbb4 + depends: + - m2-conda-epoch + - mingw-w64-ucrt-x86_64-headers-git 12.0.0.r4.gg4f2fc60ca hd8ed1ab_10 + constrains: + - mingw-w64-ucrt-x86_64-crt-git 12.0.0.r4.gg4f2fc60ca.* + license: MIT AND BSD-3-Clause-Clear + purls: [] + run_exports: {} + size: 123916 + timestamp: 1759768539535 +- conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.3.4-pyhcf101f3_0.conda + sha256: 306af633cb4ac85d04024d7c243ac2031c488bf5b0912207e7304c27a5d65a85 + md5: 1c0ebec41ef9214160da1ee6a0880fce + depends: + - python >=3.10 + - typing_extensions + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/mistune?source=hash-mapping + run_exports: {} + size: 93811 + timestamp: 1784722859728 +- conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda + sha256: d09c47c2cf456de5c09fa66d2c3c5035aa1fa228a1983a433c47b876aa16ce90 + md5: 37293a85a0f4f77bbd9cf7aaefc62609 + depends: + - python >=3.9 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/munkres?source=hash-mapping + run_exports: {} + size: 15851 + timestamp: 1749895533014 +- conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda + sha256: c81d0c8c74c3da66808f8da09d8e48f2af2d173d357d45239defaf466838edba + md5: da07c7b1588ad0a44118d28aeb31b6a6 + depends: + - importlib-metadata + - ipykernel + - ipython + - jupyter-cache >=0.5 + - myst-parser >=1.0.0 + - nbclient + - nbformat >=5.0 + - python >=3.10 + - pyyaml + - sphinx >=5 + - typing_extensions + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/myst-nb?source=hash-mapping + run_exports: {} + size: 68766 + timestamp: 1772587444587 +- conda: https://conda.anaconda.org/conda-forge/noarch/myst-parser-5.1.0-pyhd8ed1ab_0.conda + sha256: 94235bc1f769cf35029942ecb2ca796f18e730c1bf5aeef95e72680ebcfacfef + md5: 580615e59fc7c07741e4d2ab052cfc8b + depends: + - docutils >=0.20,<0.23 + - jinja2 + - markdown-it-py >=4.2.0,<4.3.0 + - mdit-py-plugins >=0.6.1,<0.7 + - python >=3.11 + - pyyaml + - sphinx >=8,<10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/myst-parser?source=hash-mapping + run_exports: {} + size: 74888 + timestamp: 1778696564508 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.11.0-pyhd8ed1ab_0.conda + sha256: eceb424236fbbb9b337a857fe5448307b57a2a3fb2db389ae37e7a8b8cdca2ab + md5: cf01a81d7960ad9c829bf2e794fcee9a + depends: + - jupyter_client >=7.0.0 + - jupyter_core >=5.4 + - nbformat >=5.2.0 + - python >=3.10 + - traitlets >=5.13 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbclient?source=hash-mapping + run_exports: {} + size: 29138 + timestamp: 1780661039538 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.17.1-hb502eef_0.conda + sha256: 6b6d96cca8e9dd34e0735b59534831e1f8206b7366c79c71e08da6ee55c50683 + md5: 02669c36935d23e5258c5dd1a5e601ab + depends: + - nbconvert-core ==7.17.1 pyhcf101f3_0 + - nbconvert-pandoc ==7.17.1 h08b4883_0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 5364 + timestamp: 1775615493260 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + sha256: ab2ac79c5892c5434d50b3542d96645bdaa06d025b6e03734be29200de248ac2 + md5: 2bce0d047658a91b99441390b9b27045 + 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.17.1 *_0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbconvert?source=hash-mapping + run_exports: {} + size: 202229 + timestamp: 1775615493260 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.17.1-h08b4883_0.conda + sha256: b576268b5b3da13b703a15d28d218fd1b552511726253575025930091e6206ae + md5: f635af333701d2ed89d70ba9adb8e2ee + depends: + - nbconvert-core ==7.17.1 pyhcf101f3_0 + - pandoc + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 5840 + timestamp: 1775615493260 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.11.1-pyhcf101f3_0.conda + sha256: d85d76827ff732e1639f50f45e4d7d3387a27abd857b194dcbb5bb4166c2a7c2 + md5: 2fbbf92e1173ae024f0b12759c1e64a1 + depends: + - jsonschema >=2.6 + - jupyter_core >=4.12,!=5.0.* + - python >=3.10 + - python-fastjsonschema >=2.15 + - traitlets >=5.1 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbformat?source=compressed-mapping + run_exports: {} + size: 107750 + timestamp: 1787133512599 +- conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio2-1.7.2-pyhcf101f3_0.conda + sha256: e6768ceef038f4d7e083de7e393f5dd7d672b937e2bda570b740f6399b686689 + md5: fcd832bfd4749e9b246112b6894f97fc + depends: + - python >=3.10 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/nest-asyncio2?source=hash-mapping + run_exports: {} + size: 15903 + timestamp: 1770973502283 +- conda: https://conda.anaconda.org/conda-forge/noarch/notebook-7.6.2-pyhcf101f3_0.conda + sha256: fb2fed7ff3ac2a94225f444984b6316cd2bf9419db0f45057334c57df3c20d0f + md5: ca3a76b7ae886c30f2ef6e0ca851b2ab + depends: + - jupyter_server >=2.19.0,<3 + - jupyter-builder >=1.0.2,<2 + - jupyterlab >=4.6.3,<4.7 + - jupyterlab_server >=2.28.0,<3 + - notebook-shim >=0.2,<0.3 + - python >=3.10 + - tornado >=6.2.0 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/notebook?source=compressed-mapping + run_exports: {} + size: 4631065 + timestamp: 1786455253264 +- 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 + run_exports: {} + size: 16817 + timestamp: 1733408419340 +- conda: https://conda.anaconda.org/conda-forge/noarch/numpydoc-1.10.0-pyhcf101f3_0.conda + sha256: 482d94fce136c4352b18c6397b9faf0a3149bfb12499ab1ffebad8db0cb6678f + md5: 3aa4b625f20f55cf68e92df5e5bf3c39 + depends: + - python >=3.10 + - sphinx >=6 + - tomli >=1.1.0 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpydoc?source=hash-mapping + run_exports: {} + size: 65801 + timestamp: 1764715638266 +- 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 + run_exports: {} + size: 30139 + timestamp: 1734587755455 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda + sha256: c432626b16768b8dab228bfb706f7060c2d462a21c516d240f68f2f902b5a044 + md5: 936687ed80f295a1f5dbcf8bd34c252c + depends: + - python >=3.9 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=hash-mapping + run_exports: {} + size: 116363 + timestamp: 1785888127370 +- 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 + run_exports: {} + size: 11627 + timestamp: 1631603397334 +- conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda + sha256: 611882f7944b467281c46644ffde6c5145d1a7730388bcde26e7e86819b0998e + md5: 39894c952938276405a1bd30e4ce2caf + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/parso?source=hash-mapping + run_exports: {} + size: 82472 + timestamp: 1777722955579 +- conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + sha256: 202af1de83b585d36445dc1fda94266697341994d1a3328fabde4989e1b3d07a + md5: d0d408b1f18883a944376da5cf8101ea + depends: + - ptyprocess >=0.5 + - python >=3.9 + license: ISC + purls: + - pkg:pypi/pexpect?source=hash-mapping + run_exports: {} + size: 53561 + timestamp: 1733302019362 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.11.4-pyhcf101f3_0.conda + sha256: 36596d60d6bc49c4c27f009ab3128c63ea50ac5d67dffc44df05ab3d78bc4669 + md5: 840f27e0254bcdc8382ac2ca32782a22 + depends: + - python >=3.10 + - python + license: MIT + purls: + - pkg:pypi/platformdirs?source=compressed-mapping + run_exports: {} + size: 27321 + timestamp: 1787603822584 +- conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.26.0-pyhd8ed1ab_0.conda + sha256: 794eec057361b41db1b06a9677eb8632adc0de81f7dcfe113bca8f0b04a23553 + md5: 3aa7e2d85645e61627c98082747dfdfe + depends: + - python >=3.10 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/prometheus-client?source=hash-mapping + run_exports: {} + size: 61554 + timestamp: 1785016068982 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.53-pyha770c72_0.conda + sha256: efe8def2c93aa34cd8d3c9af1dc4c7d312791cf769d8b2b615e32733e6df6051 + md5: 39c92a39517316e5001d645ae63d9ab9 + depends: + - python >=3.10 + - wcwidth + constrains: + - prompt_toolkit 3.0.53 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/prompt-toolkit?source=hash-mapping + run_exports: {} + size: 276081 + timestamp: 1785160613307 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.53-hd8ed1ab_0.conda + sha256: 59628c765189e99ca5d3c51f0758a325bc020dfafb8fef6068045595aaae1baf + md5: 4c7171dde29a2f2b1dac681c1154a291 + depends: + - prompt-toolkit >=3.0.53,<3.0.54.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 7083 + timestamp: 1785160614678 +- conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + sha256: a7713dfe30faf17508ec359e0bc7e0983f5d94682492469bd462cdaae9c64d83 + md5: 7d9daffbb8d8e0af0f769dbbcd173a54 + depends: + - python >=3.9 + license: ISC + purls: + - pkg:pypi/ptyprocess?source=hash-mapping + run_exports: {} + size: 19457 + timestamp: 1733302371990 +- 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 + run_exports: {} + size: 16668 + timestamp: 1733569518868 +- conda: https://conda.anaconda.org/conda-forge/noarch/pybtex-0.26.1-pyhcf101f3_0.conda + sha256: fd9b0a389b21dc2ccb11925db83a5e9e32652e87971f93c23358d51c3632d96d + md5: b0969b1326b5b9d6094dd1831eb48919 + depends: + - python >=3.10 + - pyyaml >=3.1 + - latexcodec >=1.0.4 + - importlib-metadata + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/pybtex?source=hash-mapping + run_exports: {} + size: 78091 + timestamp: 1775231969598 +- conda: https://conda.anaconda.org/conda-forge/noarch/pybtex-docutils-1.0.3-pyhcf101f3_4.conda + sha256: a0397b8fc65eabd773fe33affb726fe9d16c8f0a8ab7c3493d80c412ef2539a6 + md5: 75f19dd4b0b95ce928286e18c561cb13 + depends: + - python >=3.10 + - setuptools + - docutils >=0.14 + - pybtex >=0.16 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/pybtex-docutils?source=hash-mapping + run_exports: {} + size: 14980 + timestamp: 1765317730499 +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-3.0-pyhcf101f3_0.conda + sha256: e27e0473fc6723311a0bd48b89b616fa1b996a2f7a2b555338cbbcfb9c640568 + md5: 9c5491066224083c41b6d5635ed7107b + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pycparser?source=hash-mapping + run_exports: {} + size: 55886 + timestamp: 1779293633166 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydata-sphinx-theme-0.20.0-pyhc364b38_0.conda + sha256: 40664599ee4b5667d31b38538a06a9daad97594d4d2af8084e80cfc35ac86d6d + md5: 4539a6224d84b50aea1bcdcc01ee9802 + depends: + - accessible-pygments + - babel + - beautifulsoup4 + - docutils !=0.17.0 + - jinja2 + - pygments >=2.7 + - python >=3.11 + - requests + - sphinx >=8.2 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pydata-sphinx-theme?source=hash-mapping + run_exports: {} + size: 1312216 + timestamp: 1783604241703 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.21.0-pyhcf101f3_0.conda + sha256: f5f015ff1bc3e1b7fc08eee096b1865234189ae0b82bebdb86a5369116e42fa0 + md5: 2882dee445dfa45b0c5afce3ffb7730a + depends: + - python >=3.10 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/pygments?source=compressed-mapping + run_exports: {} + size: 959376 + timestamp: 1786995678795 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda + sha256: 417fba4783e528ee732afa82999300859b065dc59927344b4859c64aae7182de + md5: 3687cc0b82a8b4c17e1f0eb7e47163d5 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyparsing?source=hash-mapping + run_exports: {} + size: 110893 + timestamp: 1769003998136 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + sha256: d016e04b0e12063fbee4a2d5fbb9b39a8d191b5a0042f0b8459188aedeabb0ca + md5: e2fd202833c4a981ce8a65974fe4abd1 + depends: + - __win + - python >=3.9 + - win_inet_pton + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + run_exports: {} + size: 21784 + timestamp: 1733217448189 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 + md5: 461219d1a5bd61342293efa2c0c90eac + depends: + - __unix + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + run_exports: {} + size: 21085 + timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 + md5: 5b8d21249ff20967101ffa321cab24e8 + depends: + - python >=3.9 + - six >=1.5 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/python-dateutil?source=hash-mapping + run_exports: {} + size: 233310 + timestamp: 1751104122689 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.22.2-pyhcf101f3_0.conda + sha256: fc4a704822df22defce49d0fb811fdc036a1fd3b579aeaa601228e9cfd198b3d + md5: aa75b7f096d17621bc307b3025b29461 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/fastjsonschema?source=compressed-mapping + run_exports: {} + size: 254446 + timestamp: 1786892280524 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.7-h4df99d1_100.conda + sha256: 05d8d9f928cf1ba1217b3cde7fb41dfe2995feb4e6b4ef5b1a9f19ce44e18f66 + md5: c56da48fd8d5d1feb1829d0241fd338c + depends: + - cpython 3.14.7.* + - python_abi * *_cp314 + license: Python-2.0 + purls: [] + run_exports: {} + size: 50369 + timestamp: 1787153622440 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-4.2.0-pyhd8ed1ab_0.conda + sha256: 4f8ecadbd9d282b0208d6e84640573fcb6ab462307d737eedd28341964e18cc6 + md5: e5407c82510aab6a4baa31fcd4249655 + depends: + - python >=3.10 + - typing_extensions + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/python-json-logger?source=compressed-mapping + run_exports: {} + size: 19367 + timestamp: 1786872772907 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.3-pyhd8ed1ab_0.conda + sha256: 3f05db78cf8be33cf6dbc469664b8e3a01f3980d61d6d6bef48669b171896d8a + md5: eefc8d916bd2e708d76d40398ef9a1ee + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/tzdata?source=hash-mapping + run_exports: {} + size: 146862 + timestamp: 1783704822814 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + build_number: 8 + sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 + md5: 0539938c55b6b1a59b560e843ad864a4 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 6989 + timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 + md5: 870293df500ca7e18bedefa5838a22ab + depends: + - attrs >=22.2.0 + - python >=3.10 + - rpds-py >=0.7.0 + - typing_extensions >=4.4.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/referencing?source=hash-mapping + run_exports: {} + size: 51788 + timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda + sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da + md5: 4a85203c1d80c1059086ae860836ffb9 + depends: + - python >=3.10 + - certifi >=2023.5.7 + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - urllib3 >=1.26,<3 + - python + constrains: + - chardet >=3.0.2,<8 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/requests?source=hash-mapping + run_exports: {} + size: 68709 + timestamp: 1778851103479 +- 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 + run_exports: {} + 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 + run_exports: {} + 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 + run_exports: {} + size: 22913 + timestamp: 1752876729969 +- conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda + sha256: 30f3c04fcfb64c44d821d392a4a0b8915650dbd900c8befc20ade8fde8ec6aa2 + md5: 0dc48b4b570931adc8641e55c6c17fe4 + depends: + - python >=3.10 + license: 0BSD OR CC0-1.0 + purls: + - pkg:pypi/roman-numerals?source=hash-mapping + run_exports: {} + size: 13814 + timestamp: 1766003022813 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + sha256: 8fc024bf1a7b99fc833b131ceef4bef8c235ad61ecb95a71a6108be2ccda63e8 + md5: b70e2d44e6aa2beb69ba64206a16e4c6 + depends: + - __osx + - pyobjc-framework-cocoa + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/send2trash?source=hash-mapping + run_exports: {} + size: 22519 + timestamp: 1770937603551 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + sha256: 305446a0b018f285351300463653d3d3457687270e20eda37417b12ee386ef76 + md5: 6ac53f3fff2c416d63511843a04646fa + depends: + - __win + - pywin32 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/send2trash?source=hash-mapping + run_exports: {} + size: 22864 + timestamp: 1770937641143 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda + sha256: 59656f6b2db07229351dfb3a859c35e57cc8e8bcbc86d4e501bff881a6f771f1 + md5: 28eb91468df04f655a57bcfbb35fc5c5 + depends: + - __linux + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/send2trash?source=hash-mapping + run_exports: {} + size: 24108 + timestamp: 1770937597662 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-84.0.0-pyh332efcf_0.conda + sha256: 9e200ee5f9ff19a4d94e4b51c4856d53dec849f91032f345cf0c6bc3d51a7183 + md5: 62ac906f1cd582c6c264c95625cb9d6f + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/setuptools?source=compressed-mapping + run_exports: {} + size: 524488 + timestamp: 1786282924579 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/six?source=hash-mapping + run_exports: {} + size: 18455 + timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad + md5: 03fe290994c5e4ec17293cfb6bdce520 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/sniffio?source=hash-mapping + run_exports: {} + size: 15698 + timestamp: 1762941572482 +- conda: https://conda.anaconda.org/conda-forge/noarch/snowballstemmer-3.1.1-pyhd8ed1ab_0.conda + sha256: ad89284ea94821c20ff87e64b948e4afc690cf5202d14c009355b0594cf23aea + md5: 46b6abe31482f6bca064b965696ae807 + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/snowballstemmer?source=hash-mapping + run_exports: {} + size: 74456 + timestamp: 1780468201547 +- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.9.2-pyhd8ed1ab_0.conda + sha256: 056d7a2e91e303a9ee37e580f6dde0511fc3fb72476581cc337aacf2cc747613 + md5: ba33e6c8a46ee373fdf6dd8665212778 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/soupsieve?source=compressed-mapping + run_exports: {} + size: 39439 + timestamp: 1786202135509 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-9.1.0-pyhd8ed1ab_0.conda + sha256: 035ca4b17afca3d53650380dd94c564555b7ec2b4f8818111f98c15c7a991b7b + md5: aabfbc2813712b71ba8beb217a978498 + depends: + - alabaster >=0.7.14 + - babel >=2.13 + - colorama >=0.4.6 + - docutils >=0.21,<0.23 + - imagesize >=1.3 + - jinja2 >=3.1 + - packaging >=23.0 + - pygments >=2.17 + - python >=3.12 + - requests >=2.30.0 + - roman-numerals >=1.0.0 + - snowballstemmer >=2.2 + - sphinxcontrib-applehelp >=1.0.7 + - sphinxcontrib-devhelp >=1.0.6 + - sphinxcontrib-htmlhelp >=2.0.6 + - sphinxcontrib-jsmath >=1.0.1 + - sphinxcontrib-qthelp >=1.0.6 + - sphinxcontrib-serializinghtml >=1.1.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinx?source=hash-mapping + run_exports: {} + size: 1584836 + timestamp: 1767271941650 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-autobuild-2025.8.25-pyhcf101f3_0.conda + sha256: ad56a36c575f4ccec429e070dd36538cb6cb25f8d8b174a94bb9622858d9e4a4 + md5: 26d9d9a48ff32bca94581d7c91684ab8 + depends: + - colorama >=0.4.6 + - python >=3.11 + - sphinx + - starlette >=0.35 + - uvicorn >=0.25 + - watchfiles >=0.20 + - websockets >=11 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/sphinx-autobuild?source=hash-mapping + run_exports: {} + size: 19892 + timestamp: 1762270046787 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-codeautolink-0.19.0-pyhd8ed1ab_0.conda + sha256: cf0c20aee37db6a52db1be576bff550aea8eda8190e44b45a6aae2e2ae86b01f + md5: 1ee2b08263a77c64f14c2e1a13a99715 + depends: + - beautifulsoup4 >=4.8.1 + - python >=3.10 + - sphinx >=3.2.0 + constrains: + - ipython !=8.7.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/sphinx-codeautolink?source=hash-mapping + run_exports: {} + size: 51470 + timestamp: 1785419092000 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-copybutton-0.5.2-pyhd8ed1ab_1.conda + sha256: 8cd892e49cb4d00501bc4439fb0c73ca44905f01a65b2b7fa05ba0e8f3924f19 + md5: bf22cb9c439572760316ce0748af3713 + depends: + - python >=3.9 + - sphinx >=1.8 + license: MIT + license_family: MIT + purls: + - pkg:pypi/sphinx-copybutton?source=hash-mapping + run_exports: {} + size: 17893 + timestamp: 1734573117732 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda + sha256: 7f8437a97e6311bebf230cfd2ae3c5bdb2230e681c41daebdb894280bf8b4ab6 + md5: 28eddfb8b9ecdd044a6f609f985398a7 + depends: + - python >=3.11 + - sphinx >=7,<10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/sphinx-design?source=hash-mapping + run_exports: {} + size: 931118 + timestamp: 1769032711360 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-last-updated-by-git-0.3.8-pyhe01879c_0.conda + sha256: f761670b793dcc10a4a2d855de163d9dfd4016636ef093fb3e3d83ac25ed6e97 + md5: 405a232fb900fc631d2f1b5cdf01dea9 + depends: + - python >=3.9 + - sphinx >=1.8 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinx-last-updated-by-git?source=hash-mapping + run_exports: {} + size: 17546 + timestamp: 1750694360605 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-notfound-page-1.1.0-pyhd8ed1ab_0.conda + sha256: 227e87c72ff1e20833009f6ee6f9c1067534a92a14d8484619953d50f3c90f13 + md5: 08f13b15791e1b82ad8ad7d5b373ab54 + depends: + - docutils + - python >=3.9 + - sphinx + license: MIT + license_family: MIT + purls: + - pkg:pypi/sphinx-notfound-page?source=hash-mapping + run_exports: {} + size: 14204 + timestamp: 1749276617752 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-sitemap-2.9.0-pyhcf101f3_0.conda + sha256: 1be6289124207256df5dfbfe6ff0a652e313ac5c3e50560c9e510afa76eb702b + md5: 3baeff262222dc87e978a68702bc5797 + depends: + - python >=3.10 + - sphinx-last-updated-by-git + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/sphinx-sitemap?source=hash-mapping + run_exports: {} + size: 13441 + timestamp: 1759753011102 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda + sha256: d7433a344a9ad32a680b881c81b0034bc61618d12c39dd6e3309abeffa9577ba + md5: 16e3f039c0aa6446513e94ab18a8784b + depends: + - python >=3.9 + - sphinx >=5 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinxcontrib-applehelp?source=hash-mapping + run_exports: {} + size: 29752 + timestamp: 1733754216334 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-bibtex-2.7.0-pyhd8ed1ab_0.conda + sha256: 3b9c6273f95302df966a48a267b33ddf78ed6e662c7d578d3e129e259e049314 + md5: 7f562e153eedbdc92f1c3adb019a8792 + depends: + - docutils >=0.20 + - pybtex >=0.25 + - pybtex-docutils >=1.0.2 + - python >=3.10 + - sphinx >=7.4 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinxcontrib-bibtex?source=hash-mapping + run_exports: {} + size: 33489 + timestamp: 1778364472446 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda + sha256: 55d5076005d20b84b20bee7844e686b7e60eb9f683af04492e598a622b12d53d + md5: 910f28a05c178feba832f842155cbfff + depends: + - python >=3.9 + - sphinx >=5 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinxcontrib-devhelp?source=hash-mapping + run_exports: {} + size: 24536 + timestamp: 1733754232002 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda + sha256: c1492c0262ccf16694bdcd3bb62aa4627878ea8782d5cd3876614ffeb62b3996 + md5: e9fb3fe8a5b758b4aff187d434f94f03 + depends: + - python >=3.9 + - sphinx >=5 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinxcontrib-htmlhelp?source=hash-mapping + run_exports: {} + size: 32895 + timestamp: 1733754385092 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-jsmath-1.0.1-pyhd8ed1ab_1.conda + sha256: 578bef5ec630e5b2b8810d898bbbf79b9ae66d49b7938bcc3efc364e679f2a62 + md5: fa839b5ff59e192f411ccc7dae6588bb + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinxcontrib-jsmath?source=hash-mapping + run_exports: {} + size: 10462 + timestamp: 1733753857224 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-qthelp-2.0.0-pyhd8ed1ab_1.conda + sha256: c664fefae4acdb5fae973bdde25836faf451f41d04342b64a358f9a7753c92ca + md5: 00534ebcc0375929b45c3039b5ba7636 + depends: + - python >=3.9 + - sphinx >=5 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinxcontrib-qthelp?source=hash-mapping + run_exports: {} + size: 26959 + timestamp: 1733753505008 +- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-serializinghtml-2.0.0-pyhd8ed1ab_0.conda + sha256: 20b49741065fd7d3fabf98caf6d19b6436badb06b6d41f66b58f1fc2b52f37a1 + md5: f77df1fcf9af03b7287342638befca77 + depends: + - python >=3.10 + - sphinx >=5 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/sphinxcontrib-serializinghtml?source=hash-mapping + run_exports: {} + size: 30640 + timestamp: 1781260357443 +- 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 + run_exports: {} + size: 26988 + timestamp: 1733569565672 +- conda: https://conda.anaconda.org/conda-forge/noarch/starlette-1.6.0-pyhcf101f3_0.conda + sha256: 6074c6d74e86b156a61ff37f2c3f7a29bd188f05d5f490d88db96131eb945e95 + md5: 7b7d3f2bcca2be53635bd4f1166b04a7 + depends: + - anyio >=3.6.2,<5 + - python >=3.10 + - typing_extensions >=4.10.0 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/starlette?source=compressed-mapping + run_exports: {} + size: 65974 + timestamp: 1786315934415 +- conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + sha256: c47299fe37aebb0fcf674b3be588e67e4afb86225be4b0d452c7eb75c086b851 + md5: 13dc3adbc692664cd3beabd216434749 + depends: + - __glibc >=2.28 + - kernel-headers_linux-64 4.18.0 he073ed8_9 + - tzdata + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + purls: [] + run_exports: + strong: + - __glibc >=2.28,<3.0.a0 + size: 24008591 + timestamp: 1765578833462 +- conda: https://conda.anaconda.org/conda-forge/noarch/tabulate-0.10.0-pyhcf101f3_0.conda + sha256: 3f661e98a09f976775a494488beb3d35ebb00f535b169c6bd891f2e280d55783 + md5: 3b887b7b3468b0f494b4fad40178b043 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tabulate?source=hash-mapping + run_exports: {} + size: 43964 + timestamp: 1772732795746 +- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + sha256: b375e8df0d5710717c31e7c8e93c025c37fa3504aea325c7a55509f64e5d4340 + md5: e43ca10d61e55d0a8ec5d8c62474ec9e + depends: + - __win + - pywinpty >=1.1.0 + - python >=3.10 + - tornado >=6.1.0 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/terminado?source=hash-mapping + run_exports: {} + size: 23665 + timestamp: 1766513806974 +- 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 + run_exports: {} + size: 24749 + timestamp: 1766513766867 +- conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + sha256: cad582d6f978276522f84bd209a5ddac824742fe2d452af6acf900f8650a73a2 + md5: f1acf5fdefa8300de697982bcb1761c9 + depends: + - python >=3.5 + - webencodings >=0.4 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/tinycss2?source=hash-mapping + run_exports: {} + size: 28285 + timestamp: 1729802975370 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd + md5: b5325cf06a000c5b14970462ff5e4d58 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=hash-mapping + run_exports: {} + size: 21561 + timestamp: 1774492402955 +- conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.16.1-pyhcf101f3_0.conda + sha256: 03dba5917f944c6684ab44c81daacac1624cd148e4b2cae215dcec594a210c48 + md5: a79bf97561232a31447b6246c2153ab5 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/traitlets?source=hash-mapping + run_exports: {} + size: 116935 + timestamp: 1785761789772 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.16.0-h69aa097_0.conda + sha256: b141933ece3518f6d7b75dfb59451e2f26b405a44c18e2518a83e9a02e09315c + md5: c680b5747e8c4c8f23dca0bb7042a8fc + depends: + - typing_extensions ==4.16.0 pyhcf101f3_0 + license: PSF-2.0 + license_family: PSF + purls: [] + run_exports: {} + size: 94080 + timestamp: 1783002732887 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda + sha256: 2d888f90af0686044882c74193ec80a90ec1943145d94a7b1b048958acda1848 + md5: c70ad746c22219b9700931707482992c + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions?source=hash-mapping + run_exports: {} + size: 52631 + timestamp: 1783002732887 +- 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 + run_exports: {} + size: 15183 + timestamp: 1733331395943 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda + sha256: b928c30ddcb0e3f544c6eade8352737e6e610e263276b90232db6a578ef899d8 + md5: fcb489df604d100968b737f2cb6076c6 + license: LicenseRef-Public-Domain + purls: [] + run_exports: {} + size: 118849 + timestamp: 1784250406640 +- 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 + run_exports: {} + size: 23990 + timestamp: 1733323714454 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda + sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 + md5: cbb88288f74dbe6ada1c6c7d0a97223e + depends: + - backports.zstd >=1.0.0 + - brotli-python >=1.2.0 + - h2 >=4,<5 + - pysocks >=1.5.6,<2.0,!=1.5.7 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/urllib3?source=hash-mapping + run_exports: {} + size: 103560 + timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.52.4-pyh6dadd2b_0.conda + sha256: a30e60cfe04ce3e56aa87f06b61f28a893f3c1de3aacd83f45b7fe41eb684519 + md5: ebcd387e448496528a8f7af3e661861f + depends: + - __win + - click >=7.0 + - h11 >=0.8 + - python >=3.10 + - typing_extensions >=4.0 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/uvicorn?source=hash-mapping + run_exports: {} + size: 59109 + timestamp: 1787133011554 +- conda: https://conda.anaconda.org/conda-forge/noarch/uvicorn-0.52.4-pyhc90fa1f_0.conda + sha256: b74765ebebe0da43b9e0ec1d9bedc881125304ffbebd86018dcb6d7a4e2d2ee4 + md5: 2bf4d228f4df09d3e2ebee46f3a9129e + depends: + - __unix + - click >=7.0 + - h11 >=0.8 + - python >=3.10 + - typing_extensions >=4.0 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/uvicorn?source=compressed-mapping + run_exports: {} + size: 60189 + timestamp: 1787133003107 +- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.8.2-pyhd8ed1ab_0.conda + sha256: 4acf845da404e84cef1acccc66cc0156af1b83a5b5d7077b2ca19b705c561e57 + md5: 99f7755ec8648a042b0dbe906234f888 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/wcwidth?source=hash-mapping + run_exports: {} + size: 132415 + timestamp: 1782771807703 +- 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 + run_exports: {} + 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 + run_exports: {} + 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 + run_exports: {} + size: 61391 + timestamp: 1759928175142 +- conda: https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.16-pyhd8ed1ab_0.conda + sha256: bd909d9845ff269f5487a83654d6b8fe220c73148c47d602f4ee9e1283829212 + md5: 4e3aff9f40afb392477584e6a1a45b6f + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/widgetsnbextension?source=compressed-mapping + run_exports: {} + size: 901988 + timestamp: 1787044664327 +- conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + sha256: 93807369ab91f230cf9e6e2a237eaa812492fe00face5b38068735858fba954f + md5: 46e441ba871f524e2b067929da3051c2 + depends: + - __win + - python >=3.9 + license: LicenseRef-Public-Domain + purls: + - pkg:pypi/win-inet-pton?source=hash-mapping + run_exports: {} + size: 9555 + timestamp: 1733130678956 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda + sha256: 210bd31c22bb88f5e2a167df24c95bb5f152b2ada7502f9b8c49d1f5366db423 + md5: ba3dcdc8584155c97c648ae9c044b7a3 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/zipp?source=hash-mapping + run_exports: {} + size: 24190 + timestamp: 1779159948016 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + build_number: 7 + sha256: 7acaa2e0782cad032bdaf756b536874346ac1375745fb250e9bdd6a48a7ab3cd + md5: a44032f282e7d2acdeb1c240308052dd + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - _openmp_mutex >=4.5 + size: 8325 + timestamp: 1764092507920 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-26.1.0-py314h61c6340_0.conda + sha256: ca954d29945fc070549656374d2d093370513c7b5b03ed6dd90e3e28040a5ae6 + md5: f851200bba7198af60f999578267cdf4 + depends: + - __osx >=11.0 + - cffi >=2.0.0b1 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + run_exports: {} + size: 32051 + timestamp: 1787248673403 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/blas-2.309-accelerate.conda + build_number: 9 + sha256: 5672e4772e459d6bd1a0138e2146ae5c52dfbdeb53ad7b881af2ca31b80f4250 + md5: 9871fe8f2c28448c83dff3b0f682b2f5 + depends: + - blas-devel 3.11.0 9*_accelerate + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 18398 + timestamp: 1786058878302 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/blas-devel-3.11.0-9_h55bc449_accelerate.conda + build_number: 9 + sha256: cffd54200d9a33820d123b1f29c7b243ff29c47473833a59860ba2c984ecc1aa + md5: 0fe2c92600d1483811316c2090233161 + depends: + - libblas 3.11.0 9_h3d1d584_accelerate + - libcblas 3.11.0 9_h752f6bc_accelerate + - liblapack 3.11.0 9_hcb0d94e_accelerate + - liblapacke 3.11.0 9_hbdd07e9_accelerate + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 17703 + timestamp: 1786058859766 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-hf00d406_3.conda + sha256: 7050e1b11876219bd0df375ef3d83fd00f94fb4e13c1ffb21dede0c506893079 + md5: aa7df8174ee3b34a5ad8a3160429db68 + depends: + - __osx >=11.0 + - brotli-bin 1.2.0 he4a93e4_3 + - libbrotlidec 1.2.0 h5295a6a_3 + - libbrotlienc 1.2.0 h2ddc9cb_3 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 20767 + timestamp: 1786622887445 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-he4a93e4_3.conda + sha256: 1e92cea587c2eaab169e45dae01c149b9889a8249eda296b8b6db39aee708531 + md5: d9de6c0ad7e008afdf62fb2ffd450b4a + depends: + - __osx >=11.0 + - libbrotlidec 1.2.0 h5295a6a_3 + - libbrotlienc 1.2.0 h2ddc9cb_3 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 18962 + timestamp: 1786622878369 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314hee34562_3.conda + sha256: 3cdfc0a96de4717fc309e39133e2a192f4e1df96680577e1d48804021d1726eb + md5: d3a28add84f2412a562355f89ef5e0f5 + depends: + - __osx >=11.0 + - libcxx >=21 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 h1dcdb26_3 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=compressed-mapping + run_exports: {} + size: 365272 + timestamp: 1786623009364 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda + sha256: 8ec22f0ba25cbfc2e64d70cf29459eccd7ffdf6436f6a6ff15bbfef799f7d4f6 + md5: b50612e7d190b8061ab4e7dc119cf4d5 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 124965 + timestamp: 1785906749812 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cairo-1.18.4-he0f2337_1.conda + sha256: cde9b79ee206fe3ba6ca2dc5906593fb7a1350515f85b2a1135a4ce8ec1539e3 + md5: 36200ecfbbfbcb82063c87725434161f + depends: + - __osx >=11.0 + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.1,<79.0a0 + - libcxx >=19 + - libexpat >=2.7.3,<3.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + - libglib >=2.86.3,<3.0a0 + - libpng >=1.6.53,<1.7.0a0 + - libzlib >=1.3.1,<2.0a0 + - pixman >=0.46.4,<1.0a0 + license: LGPL-2.1-only or MPL-1.1 + purls: [] + run_exports: + weak: + - cairo >=1.18.4,<2.0a0 + size: 900035 + timestamp: 1766416416791 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm22_1_hbe26303_5.conda + sha256: c2431becc11a32e157a1c22c44f368773c009e298ba0127c89e614c8d3493a36 + md5: ee35bbae0edb9cc3b69445b0e8f90773 + depends: + - cctools_impl_osx-arm64 1030.6.3 llvm22_1_h7bf7afb_5 + - ld64 956.6 llvm22_1_h5b97f1b_5 + - libllvm22 >=22.1.8,<22.2.0a0 + license: APSL-2.0 + license_family: Other + purls: [] + run_exports: {} + size: 24351 + timestamp: 1785270934554 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm22_1_h7bf7afb_5.conda + sha256: 4e973a6236849d4f52b4463609654980ce60e6cd3cad71de9480f63ff9767548 + md5: 65296f920674a115310cc3f3ce1bc8fc + depends: + - __osx >=11.0 + - ld64_osx-arm64 >=956.6,<956.7.0a0 + - libcxx + - libllvm22 >=22.1.8,<22.2.0a0 + - libzlib >=1.3.2,<2.0a0 + - llvm-tools 22.1.* + - sigtool-codesign + constrains: + - ld64 956.6.* + - cctools 1030.6.3.* + - clang 22.1.* + license: APSL-2.0 + license_family: Other + purls: [] + run_exports: {} + size: 752126 + timestamp: 1785270918177 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.1.1-py314h618e29d_2.conda + sha256: 77b0bb0f3fd2d28b6bbd216d370d98320835b8e1df4c86a478a1d0391d1913fe + md5: 1572fc59fc2b1461f47b0d6907acef30 + depends: + - __osx >=11.0 + - libffi >=3.7.0,<3.8.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + run_exports: {} + size: 292307 + timestamp: 1786775143512 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-22-22.1.8-default_h54a73ef_9.conda + sha256: 9a6cec88635856d7f62ca615c95e37f4674d8f0bf4ef8e7c39ffcf513aa1f76c + md5: 46a43a8b768f4abd45995a0ec92581f3 + depends: + - compiler-rt22 ==22.1.8 + - libclang-cpp22.1 ==22.1.8 default_h79071a4_9 + - libcxx >=22.1.8 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - libllvm22 >=22.1.8,<22.2.0a0 + - libclang-cpp22.1 >=22.1.8,<22.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 924796 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-22.1.8-default_cfg_ha85103e_9.conda + sha256: 16f156f01b08812632a7cbab32b89744fc67049cd8a304c5c18b7e33137c55ce + md5: a43e75e98ff89a12eb00c4ff8c129708 + depends: + - clang-22 ==22.1.8 default_* + - llvm-openmp >=22.1.8 + - clang_impl_osx-arm64 ==22.1.8 default_h79071a4_9 + - cctools + - ld64 + - ld64_osx-arm64 * llvm22_1_* + - llvm-tools ==22.1.8 + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 32197 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-22.1.8-default_h79071a4_9.conda + sha256: bbb3e4e7e09b43880b436b0d000612cf3ab4e9f6344a2e9e3cc77e734b2fa62c + md5: d61a52eada41177a1734e2fae4715878 + depends: + - libclang13 >=22.1.8 + - libclang-cpp22.1 >=22.1.8,<22.2.0a0 + - libcxx >=22.1.8 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - libllvm22 >=22.1.8,<22.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 116207 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-22.1.8-default_h79071a4_9.conda + sha256: 36ac0e4d0430832b68f36e255fe53c9d07180d0cf756d14a600a7c377c007e79 + md5: 2aa1656f46395a10bb9e666b7398a368 + depends: + - clang-22 ==22.1.8 default_* + - compiler-rt_osx-arm64 ==22.1.8 + - compiler-rt ==22.1.8 + - cctools_impl_osx-arm64 + - ld64_osx-arm64 * llvm22_1_* + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 31777 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-22.1.8-default_cfg_h9e28d6e_9.conda + sha256: 02ed1159d3cf1a025003fc2db6a87c4a56022e47137ee9f2d6c35d7868ba7d68 + md5: 8ddfb874a270db5195d80ed3518b09af + depends: + - clang ==22.1.8 default_cfg_ha85103e_9 + - clangxx_impl_osx-arm64 ==22.1.8 default_* + - libcxx-devel 22.1.* + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 32255 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-22.1.8-default_h350d358_9.conda + sha256: 8a4e922fd277e36b7392fe9cbfb7ac3ae9e4743f6f75581421e83088cb7f6b71 + md5: cf27f388b4cac48c7c9a79434975ba82 + depends: + - clang-22 ==22.1.8 default_* + - clang_impl_osx-arm64 ==22.1.8 default_h79071a4_9 + - clang-scan-deps ==22.1.8 default_h79071a4_9 + - libcxx-devel 22.1.* + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 31898 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-22.1.8-hce30654_2.conda + sha256: 28c01956aefbe38a8bddde58bb2398789fd580ffb341a12c54f44a542fa1a358 + md5: fa14e650717aac340bcc3251bab8117b + depends: + - compiler-rt22 22.1.8 hdb3d66b_2 + - libcompiler-rt 22.1.8 hdb3d66b_2 + constrains: + - clang 22.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 16634 + timestamp: 1787293624982 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt22-22.1.8-hdb3d66b_2.conda + sha256: cfa490c27082b9aca7a087548c2608daf5af2644f0eb8345fba7d4baa45fd03d + md5: da9362e9de3e1f80c9786a268ff22bfa + depends: + - __osx >=11.0 + - compiler-rt22_osx-arm64 22.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: {} + size: 99807 + timestamp: 1787293624048 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/contourpy-1.3.3-py314hf8a3a22_4.conda + sha256: 754ab72f1c1ae99ef7c57995f59224dc9632cbd6731fe7e6277437fd01d43156 + md5: cddc851000ce131d757678c2f329eaad + depends: + - numpy >=1.25 + - python + - python 3.14.* *_cp314 + - __osx >=11.0 + - libcxx >=19 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/contourpy?source=hash-mapping + run_exports: {} + size: 290405 + timestamp: 1769156069514 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.21-py314he609de1_0.conda + sha256: fd6df772cdb30d01fa0d405ed637f420a9f2194fe931f967e8c67d95b504f8b4 + md5: da29307f59fb7a63f686ec20724fecf9 + depends: + - python + - libcxx >=19 + - __osx >=11.0 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + run_exports: {} + size: 2776045 + timestamp: 1780390212997 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fontconfig-2.18.3-h81aa574_1.conda + sha256: 004570d35fb0eff73ce3ae49b209a47622d0c2e580dd0dc4c61d59626b386a09 + md5: 8ac8cc3fe744b484de4387703134d8b2 + depends: + - __osx >=11.0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libintl >=0.25.1,<1.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + size: 265659 + timestamp: 1786667932256 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.14.3-hce30654_2.conda + sha256: 90681f1d0658cb2fd49a074f644eb4774272499290487a4bebb1c4df01d6997b + md5: 2f4cc7dc2e6622591735c49dda1b92aa + depends: + - libfreetype 2.14.3 hce30654_2 + - libfreetype6 2.14.3 h2ed5691_2 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + size: 175388 + timestamp: 1786641016583 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fribidi-1.0.16-h84a0fba_1.conda + sha256: 6dd18694340b84290bb1906cc1359502b974aada6a8476cfe6dec3ce0e860af8 + md5: 2bb7d7dd91116b8c85e805b0e08cc67b + depends: + - __osx >=11.0 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - fribidi >=1.0.16,<2.0a0 + size: 60230 + timestamp: 1785912572097 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/graphite2-1.3.15-h784d473_1.conda + sha256: 471f34a187fdb4f2df33e26f2e471b16c239a5b277903f643d9c3a8c9a9f44ec + md5: 0c7b78d9ffff4f5a6ca28d346f734d8f + depends: + - libcxx >=19 + - __osx >=11.0 + license: LGPL-2.0-or-later + license_family: LGPL + purls: [] + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 + size: 86493 + timestamp: 1786118637573 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/greenlet-3.5.5-py314he609de1_0.conda + sha256: d960aefe961553b75450b7584f2fad7693ed1fac423da0fc5a9d649c48d2a019 + md5: ae860c6208235503f82ef3019461d410 + depends: + - python + - __osx >=11.0 + - libcxx >=19 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/greenlet?source=compressed-mapping + run_exports: {} + size: 274201 + timestamp: 1786384265137 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda + sha256: 6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416a43 + md5: a5efc0b42bb8b42e97d0a29ae3e3c187 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 14070242 + timestamp: 1786545847761 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.5.0-py314hf8a3a22_0.conda + sha256: 840de1b0ba2fa646475bc53ba0f723c8a13e66139633a070831b8279deaa7c64 + md5: eb1465d8a644ef290d18fb86af6e9bc4 + depends: + - python + - python 3.14.* *_cp314 + - libcxx >=19 + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/kiwisolver?source=hash-mapping + run_exports: {} + size: 69284 + timestamp: 1773067285911 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h34f8a20_2.conda + sha256: aaea1d42b07769920db2af7471ece9399d2613448863da64ad8272998db5db34 + md5: 15235dd10450d67bc25ccafd5b46d2bc + depends: + - __osx >=11.0 + - libcxx >=21 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 1165740 + timestamp: 1786762145768 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.19.1-hdfa7624_1.conda + sha256: ccb5598fad3694e79bf54f0eb812e3b3c3dd63d1497e631f5978800eadb9bcc4 + md5: d2f2c7c10e2957647d45589b7701a453 + depends: + - __osx >=11.0 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - libtiff >=4.7.1,<4.8.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - lcms2 >=2.19.1,<3.0a0 + size: 213747 + timestamp: 1780212240694 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm22_1_h5b97f1b_5.conda + sha256: 649aed47b17fb6dd0036972eb67cda49d930edb33bfbd42080d0f56e689927cc + md5: e36ce4ef652fd1d571d32df59e6aafe6 + depends: + - ld64_osx-arm64 956.6 llvm22_1_h692d5aa_5 + - libllvm22 >=22.1.8,<22.2.0a0 + constrains: + - cctools_osx-arm64 1030.6.3.* + - cctools 1030.6.3.* + license: APSL-2.0 + license_family: Other + purls: [] + run_exports: {} + size: 21744 + timestamp: 1785270927117 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm22_1_h692d5aa_5.conda + sha256: 0ae96297b92a8148219d3450b989caaa37c6a8f03c3b891d204946e9b2a8f69d + md5: b84ec86a7de90fd23133d5f527943329 + depends: + - __osx >=11.0 + - libcxx + - libllvm22 >=22.1.8,<22.2.0a0 + - sigtool-codesign + - tapi >=1600.0.11.8,<1601.0a0 + constrains: + - cctools_impl_osx-arm64 1030.6.3.* + - ld64 956.6.* + - cctools 1030.6.3.* + - clang 22.1.* + license: APSL-2.0 + license_family: Other + purls: [] + run_exports: {} + size: 1038789 + timestamp: 1785270893798 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.2.0-h1eee2c3_0.conda + sha256: c97aa17d16d2ac332ba9f184e82ce8f72dcb10e9a10c5f299030be2d44e191b9 + md5: e429aec4037d5cb8fd34ded9f5dadd39 + depends: + - __osx >=11.0 + - libcxx >=19 + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - lerc >=4.2.0,<5.0a0 + size: 166477 + timestamp: 1785036480092 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-9_h3d1d584_accelerate.conda + build_number: 9 + sha256: 700b9977c9204195efa3ee0913895e344f264fec7a9a5ec0e886e7b2cb4de9b2 + md5: 33f464f01650d5be2d9c2d05533e3d97 + depends: + - __osx >=11.0 + - libgfortran + - libgfortran5 >=14.4.0 + constrains: + - blas 2.309 accelerate + - libcblas 3.11.0 9*_accelerate + - liblapack 3.11.0 9*_accelerate + - liblapacke 3.11.0 9*_accelerate + - mkl <2027 + track_features: + - blas_accelerate + - blas_accelerate_2 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 + size: 2822826 + timestamp: 1786058830452 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-h1dcdb26_3.conda + sha256: 5e62b856b2e77ce98db44133bacab1281b42c1040dcbd69dbacfb80890cff5b0 + md5: b457450ba3f27c4749783c0204bd17b0 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + size: 80027 + timestamp: 1786622846050 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-h5295a6a_3.conda + sha256: 510c9fce0d9ffcf41741dd96fc05db381672109d5665ef002c2e58f0d4ca0118 + md5: e07a99c6fdd984f4d588060f2f936bf4 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 h1dcdb26_3 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 29935 + timestamp: 1786622857695 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-h2ddc9cb_3.conda + sha256: eac412417eee2e93c62e9d53559f1f9c14f40b6c41e2c432af8b517596898dd1 + md5: 954c78a9f591bfb12c79beaff7338ec8 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 h1dcdb26_3 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 + size: 295650 + timestamp: 1786622868044 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-9_h752f6bc_accelerate.conda + build_number: 9 + sha256: b3afe0b26f1d67e1d74f7a93aca436814f8a508a7ff304c4226e6add45bb36b8 + md5: ca9ab16cae919037f520e8a0e3238857 + depends: + - libblas 3.11.0 9_h3d1d584_accelerate + constrains: + - blas 2.309 accelerate + - liblapack 3.11.0 9*_accelerate + - liblapacke 3.11.0 9*_accelerate + track_features: + - blas_accelerate + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 + size: 18170 + timestamp: 1786058842226 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp22.1-22.1.8-default_h79071a4_9.conda + sha256: dee9afef1b1e45bb2fa7fed485d095e3184a34cc06697ca3df7b46b5cb618f7b + md5: 55ee288cf2d7e6d4581a714f7da59914 + depends: + - libcxx >=22.1.8 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - libllvm22 >=22.1.8,<22.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + weak: + - libclang-cpp22.1 >=22.1.8,<22.2.0a0 + size: 15941619 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-22.1.8-default_h54a73ef_9.conda + sha256: 93a3485f7c08dc4f6528913801e60e8bd93742d5058d335aa482548d9a50678b + md5: 349f80d4b7d80b25c88c00cb5eac5f74 + depends: + - libclang-cpp22.1 ==22.1.8 default_h79071a4_9 + - libcxx >=22.1.8 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - libllvm22 >=22.1.8,<22.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + weak: + - libclang13 >=22.1.8 + size: 9988216 + timestamp: 1787349779831 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-22.1.8-hdb3d66b_2.conda + sha256: ed70856638465fa1e3dbce41b7512425a63789774368e4b9878249517daeecad + md5: 1ea9adef104f7304dc445153f1f19274 + depends: + - __osx >=11.0 + constrains: + - compiler-rt >=9.0.1 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + weak: + - libcompiler-rt >=22.1.8 + size: 1374400 + timestamp: 1787293619574 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda + sha256: a2e7abab5add9750fab064c024394de48e49f97631c605ad5db5c8ac3fc769ef + md5: 89f76a2a21a3ec3ec983b5eb237c4113 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + run_exports: {} + size: 569349 + timestamp: 1781670209146 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-22.1.8-h6dc3340_0.conda + sha256: e734ac1ed426d09363d242674a286dc004f041ad1167e73912e11d3634cee09d + md5: f7784a43f0ed7158e918fd8ec0843b47 + depends: + - libcxx >=22.1.8 + - libcxx-headers >=22.1.8,<22.1.9.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + run_exports: {} + size: 21687 + timestamp: 1781670229781 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-he7e0567_1.conda + sha256: d896f4aa4ce4c590c2838678cb1917356fdb461d2a189991c0280c818c362172 + md5: 78650d671cb56909bb3e5c13bce310f9 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 + size: 55727 + timestamp: 1785909153744 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321h26f1114_1.conda + sha256: 257c926f19e32bdb981fc674c76966049b6fc73f706bae58e9fed8757ad1da70 + md5: 843ef89082f368cb889305084d3b483c + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libedit >=3.1.20250104,<3.2.0a0 + size: 107742 + timestamp: 1786616721640 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.1-hf6b4638_1.conda + sha256: 5af74261101e3c777399c6294b2b5d290e508153268eb2e9ff99c4d69834612f + md5: a915151d5d3c5bf039f5ccc8402a436f + depends: + - __osx >=11.0 + constrains: + - expat 2.8.1.* + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 69362 + timestamp: 1781203631990 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-hcf2aa1b_0.conda + sha256: 2c6ac9a6cd65af89b2bd448518bb1e13b44a2e48c0d469398e37bcfc0092e832 + md5: 92e8690d170d46d768c32553458c0105 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 43734 + timestamp: 1783521647536 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.3-hce30654_2.conda + sha256: 19ce8bd320414cb6b9889ecbf48a3ded848b0d1068b76ff6bea099bd7387d6f3 + md5: ee1fc5bba400ff0cae27fbf141a1ae0c + depends: + - libfreetype6 >=2.14.3 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: {} + size: 8367 + timestamp: 1786641013393 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.3-h2ed5691_2.conda + sha256: d9b203d6484ad491b5b5f33d49a9d7a91189d776a9adae53d2b63af18ec11e6a + md5: 881cfb44ea02cc9849f612725a959660 + depends: + - __osx >=11.0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - freetype >=2.14.3 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: {} + size: 340923 + timestamp: 1786641012794 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-16.2.0-h3cf6597_4.conda + sha256: 00b8d07ea98344c72c6e332a09b8060f4176849d5fd0eb78dd5b30176ad97ca4 + md5: 408af8d9d5226ff45ff04756ff1aa91e + depends: + - _openmp_mutex + constrains: + - libgcc-ng ==16.2.0=*_4 + - libgomp 16.2.0 4 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 365758 + timestamp: 1787617459249 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-16.2.0-h07b0088_4.conda + sha256: 7582efbbffc6964093afd80e01c2ac60d89aa4e404cac664544675b9d4d1c5e7 + md5: aa6c627acd0f5709d9c79bf708a7b81b + depends: + - libgfortran5 16.2.0 hdb7a957_4 + constrains: + - libgfortran-ng ==16.2.0=*_4 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 99624 + timestamp: 1787617544212 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-16.2.0-hdb7a957_4.conda + sha256: 902719c38c7a390d305435a362dc83893754c3f933569a38347c434cd1c12540 + md5: d54390644d893d50e739b19145aae45f + depends: + - libgcc >=16.2.0 + constrains: + - libgfortran 16.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + purls: [] + run_exports: {} + size: 554806 + timestamp: 1787617465010 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libglib-2.88.3-ha531971_1.conda + sha256: c9f7273bbe06d1693ff3a2b6f8b49b74e2ef6cbac2cead7aae767f2f5191b7aa + md5: 70a6bcf13dc0dd00fe3fe91190d38771 + depends: + - __osx >=11.0 + - pcre2 >=10.47,<10.48.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libintl >=0.25.1,<1.0a0 + - libiconv >=1.18,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - glib >2.66 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - libglib >=2.88.3,<3.0a0 + size: 4447961 + timestamp: 1786457780347 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libharfbuzz-14.3.1-hcda0f7c_0.conda + sha256: 67af14f8fbf9b9725890f728179d933ac35a95a6b50f37b7b568a11bfa8a4c1d + md5: 1631ca9ffe7d368850904baa1df1abf4 + depends: + - __osx >=11.0 + - cairo >=1.18.4,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libcxx >=21 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.88.3,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 953252 + timestamp: 1786970947180 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda + sha256: 689a14968267f2f97c07112fca5636e7d756036b9aee969911267c20bd3eea1f + md5: 17f4744c0873e9f77ac9b5cd0a27c187 + depends: + - __osx >=11.0 + license: LGPL-2.1-only + purls: [] + run_exports: + weak: + - libiconv >=1.18,<2.0a0 + size: 750816 + timestamp: 1787033961086 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda + sha256: 99d2cebcd8f84961b86784451b010f5f0a795ed1c08f1e7c76fbb3c22abf021a + md5: 5103f6a6b210a3912faf8d7db516918c + depends: + - __osx >=11.0 + - libiconv >=1.18,<2.0a0 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - libintl >=0.25.1,<1.0a0 + size: 90957 + timestamp: 1751558394144 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.2.0-h84a0fba_1.conda + sha256: 05006418f9392c9b723e8428808db106de0350a497832f95f921b85ff1072310 + md5: b2f8c8e5a7651a1d7c05404c3a159517 + depends: + - __osx >=11.0 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + purls: [] + run_exports: + weak: + - libjpeg-turbo >=3.2.0,<4.0a0 + size: 558459 + timestamp: 1785896382474 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-9_hcb0d94e_accelerate.conda + build_number: 9 + sha256: 181c3fc8ed3fa5728ad8e418aee37c94c556b169ab6fbc620b448f1b5cf0448e + md5: 31673241e570e2a408576fa62f55215b + depends: + - libblas 3.11.0 9_h3d1d584_accelerate + constrains: + - blas 2.309 accelerate + - libcblas 3.11.0 9*_accelerate + - liblapacke 3.11.0 9*_accelerate + track_features: + - blas_accelerate + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 + size: 18148 + timestamp: 1786058849920 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapacke-3.11.0-9_hbdd07e9_accelerate.conda + build_number: 9 + sha256: 8cb75e86c882585437003b2be6a5bac9418678cb934e5f154babb9a4b711ead8 + md5: d2dbdc0cbf29754e1575c0a78f9e66dd + depends: + - libblas 3.11.0 9_h3d1d584_accelerate + - libcblas 3.11.0 9_h752f6bc_accelerate + - liblapack 3.11.0 9_hcb0d94e_accelerate + constrains: + - blas 2.309 accelerate + track_features: + - blas_accelerate + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - liblapacke >=3.11.0,<3.12.0a0 + size: 18188 + timestamp: 1786058856697 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm22-22.1.8-h759d1ac_2.conda + sha256: 0d9f5b0d13e3b6b94132ebe5ce79edbd7790e089249852ce3e061888f1b0a0c5 + md5: 6f1791ed2becb128eb25d6819fea99b6 + depends: + - __osx >=11.0 + - libcxx >=21 + - libxml2 + - libxml2-16 >=2.15.3 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + run_exports: + weak: + - libllvm22 >=22.1.8,<22.2.0a0 + size: 30239322 + timestamp: 1787282732568 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda + sha256: 23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4311 + md5: 8ab10323068b107661a4b9a4af84f3b5 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 91720 + timestamp: 1786348695846 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_2.conda + sha256: 04cc136c5a956a73aa14e0a160b5822b0b29714e67b299fa1b1fd16dbcba5366 + md5: ff33a4dbd93abc8a798cc4e0e7c8136d + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 73289 + timestamp: 1786651074391 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.58-hf5e6511_1.conda + sha256: f88da60b348ee1f3e1a9c20fe02142fdafe889f08da0b1cc33c1f3f14460239d + md5: e0466c58fd07db190b9a81b5e58539f2 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: zlib-acknowledgement + purls: [] + run_exports: + weak: + - libpng >=1.6.58,<1.7.0a0 + size: 290219 + timestamp: 1786616561185 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libraqm-0.11.0-h45af499_0.conda + sha256: b110f7f9b2cec61ea793c521950414e00cd64826e18aeb4ab40369acf05c0039 + md5: 46ea0eb4e71bffa35ab7070678bcb053 + depends: + - __osx >=11.0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libharfbuzz >=14.2.1 + - fribidi >=1.0.16,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libraqm >=0.11.0,<0.12.0a0 + size: 31333 + timestamp: 1784850348342 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda + sha256: fcfa03afe31f40dfabf011629d99836adbebbc3ed1b38c7e9eee9ffc7581975b + md5: c70eb797aa92a294b09ef8f41f6bd578 + depends: + - __osx >=11.0 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 36651 + timestamp: 1786115069018 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.22-h74c22ad_2.conda + sha256: 1cc97c217b103145e67ae6f928d0ae11ebc56879dfd10d739539624f0de80f86 + md5: ea78b9246e47aade6c94db52b1c9b5a4 + depends: + - __osx >=11.0 + license: ISC + purls: [] + run_exports: + weak: + - libsodium >=1.0.22,<1.0.23.0a0 + size: 249624 + timestamp: 1787225816699 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-hca69786_1.conda + sha256: 839b31d4830e896b4d315b551d27f2bb08026bc946df04bcc360d8627c3ba2cd + md5: fde96d40ebe9a9cb34e4122380189ddb + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 942754 + timestamp: 1787051243846 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.2-h282da08_0.conda + sha256: 253153cabf9469170e02b21a6bc9aa598048e7c34966b1103af52d27d2a708a4 + md5: 6fa87106b3c041ad6d965a9411e79b94 + depends: + - __osx >=11.0 + - lerc >=4.1.0,<5.0a0 + - libcxx >=19 + - libdeflate >=1.25,<1.26.0a0 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + purls: [] + run_exports: + weak: + - libtiff >=4.7.2,<4.8.0a0 + size: 387825 + timestamp: 1783085754081 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h202fb40_1.conda + sha256: 0ff54650d470c7e54cbeffdd53a8c063e055a7bcf784388c0385ce5c4741b0f4 + md5: 168a13e329259710b28277abc1395b8e + depends: + - __osx >=11.0 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 + size: 294522 + timestamp: 1785955350410 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hbffa61f_1.conda + sha256: 81f9b4fb64d977c19474d1b5616974757aaac21d55401ea105f21022b386bd28 + md5: 923bf656578743d064f352f0b56ee658 + depends: + - __osx >=11.0 + - pthread-stubs + - xorg-libxau >=1.0.12,<2.0a0 + - xorg-libxdmcp >=1.1.5,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxcb >=1.17.0,<2.0a0 + size: 324264 + timestamp: 1787077544793 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h5ef1a60_1.conda + sha256: 2ca61d8287339c726b151fa612e83d2afa1418b89fa17694c873dc231bc9b077 + md5: f86c0b8ac5c866049717b55df1049c2c + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - libxml2 2.15.3 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 466188 + timestamp: 1787237580766 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.3-h5654f7c_1.conda + sha256: ff1b70683ccb82f8aa7f3eda53405a2036d849daba4e4e622f330dcd49d37700 + md5: 06a3f8eb5cdde56b2d10b49ae3337954 + depends: + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.3 h5ef1a60_1 + - libzlib >=1.3.2,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.3 + size: 41264 + timestamp: 1787237585903 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda + sha256: a18fa5d5bac452401459f966cf0d872224e8080c4ff93c77e168d43ab42ef9d7 + md5: f39288f0ea63ae962e1a2e4f355a0d75 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 47822 + timestamp: 1785277049190 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.8-hc225544_1.conda + sha256: aa95fe355ec9fbf5d9816e155b9678cc98b749d3245bff56ca02f2a01239f5ac + md5: 4d317ff37f520b0d25d634cb996823cd + depends: + - __osx >=11.0 + constrains: + - intel-openmp <0.0a0 + - openmp 22.1.8|22.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + strong: + - llvm-openmp >=22.1.8 + size: 287782 + timestamp: 1787293144681 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22-22.1.8-h79441dc_2.conda + sha256: 7034bea200b67b6a1effbf350cb34518786715a2640247f85173d9ee4159ad11 + md5: dffb5b6ba46221e9c287d09721e8ac9f + depends: + - __osx >=11.0 + - libcxx >=21 + - libllvm22 22.1.8 h759d1ac_2 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + run_exports: {} + size: 17968840 + timestamp: 1787282818022 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22.1.8-hdb3d66b_2.conda + sha256: cf82447e24d3d46d7d17521ee8875eef6132313feda4f8dd2cfac989d5184189 + md5: 0b33be5a03e3f7ac75fdbbde668d8185 + depends: + - __osx >=11.0 + - libllvm22 22.1.8 h759d1ac_2 + - llvm-tools-22 22.1.8 h79441dc_2 + constrains: + - clang 22.1.8 + - clang-tools 22.1.8 + - llvm 22.1.8 + - llvmdev 22.1.8 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + run_exports: {} + size: 51998 + timestamp: 1787282867589 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvmlite-0.48.0-py314h582f951_1.conda + sha256: 2e4b585c7612892ea2f6328a32c8c8a7b231cada67a7b62124043827f849718f + md5: 6441a7f3066baffbfe9952d1cf1ee8ad + depends: + - python + - libcxx >=19 + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/llvmlite?source=hash-mapping + run_exports: {} + size: 30238668 + timestamp: 1784043454464 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + sha256: 411153d14ee0d98be6e3751cf5cc0502db17bce2deebebb8779e33d29d0e525f + md5: d33c0a15882b70255abdd54711b06a45 + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + run_exports: {} + size: 27256 + timestamp: 1772445397216 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-3.11.1-py314h314fc0d_2.conda + sha256: ea350f06df2581e68b9f5e1d029ad603c4044d9afff1294ca9315ac986b5d05f + md5: 710b3448473bb1bff68d2ba19cbc6c58 + depends: + - matplotlib-base >=3.11.1,<3.11.2.0a0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - tornado >=5 + license: PSF-2.0 + license_family: PSF + purls: [] + run_exports: {} + size: 14958 + timestamp: 1785211126869 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-base-3.11.1-py314h27b0870_2.conda + sha256: 363b319e21cf4782fe264b96494c6be949db79d0d0ba126be1a1a94a5e96aae6 + md5: 41fb78906bf657af4fbdcf8c67f41c11 + depends: + - __osx >=11.0 + - contourpy >=1.0.1 + - cycler >=0.10 + - fonttools >=4.28.2 + - freetype + - kiwisolver >=1.3.1 + - libcxx >=19 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libraqm >=0.11.0,<0.12.0a0 + - numpy >=1.25 + - numpy >=1.25,<3 + - packaging >=20.0 + - pillow >=9 + - pyparsing >=3 + - python >=3.14,<3.15.0a0 + - python-dateutil >=2.7 + - python_abi 3.14.* *_cp314 + - qhull >=2020.2,<2020.3.0a0 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/matplotlib?source=hash-mapping + run_exports: {} + size: 8776291 + timestamp: 1785211103855 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda + sha256: 7024a48c8c0d0114ed4ab53c76bf9275d50e91ba7cea367a9aead638d3c29c68 + md5: 3dfa0d0316dc246cd44937a557de4501 + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + purls: [] + run_exports: + weak: + - ncurses >=6.6,<7.0a0 + size: 804298 + timestamp: 1786355189145 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numba-0.66.0-py314h705d3de_1.conda + sha256: 891dc017080e256abf5d71ff3b2a76d1440c41ef857303437cbee4d163be842a + md5: 36963987dbd28a0522a99625f54012f8 + depends: + - python + - llvmlite >=0.48.0,<0.49.0a0 + - numpy >=1.22.3,<2.5 + - llvm-openmp >=19.1.7 + - __osx >=11.0 + - libcxx >=19 + - python_abi 3.14.* *_cp314 + - numpy >=1.23,<3 + constrains: + - tbb >=2021.6.0 + - libopenblas >=0.3.18,!=0.3.20 + - cuda-version >=11.2 + - cudatoolkit >=11.2 + - scipy >=1.0 + - cuda-python >=11.6 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/numba?source=hash-mapping + run_exports: {} + size: 6168367 + timestamp: 1785940733623 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.6-py314hb79c6fa_0.conda + sha256: 538064b78042cd2751664f00c6255ecce81b38e9fa6dd9c1863327e6c759ed4a + md5: e64e47cb372d92e3425816a2918f4605 + depends: + - python + - __osx >=11.0 + - libcxx >=19 + - libblas >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + - liblapack >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + run_exports: + weak: + - numpy >=1.23,<3 + size: 6995531 + timestamp: 1779169217034 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda + sha256: 60aca8b9f94d06b852b296c276b3cf0efba5a6eb9f25feb8708570d3a74f00e4 + md5: 4b5d3a91320976eec71678fad1e3569b + depends: + - __osx >=11.0 + - libcxx >=19 + - libpng >=1.6.55,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - openjpeg >=2.5.4,<3.0a0 + size: 319697 + timestamp: 1772625397692 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.3-hd24854e_1.conda + sha256: 66be2283b5b37dcda1332b5e74c1782a8cb14fd2e62e0d38017c2d35bf73c119 + md5: 65d1906712b85d1679263c518d011b5b + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - openssl >=3.6.3,<4.0a0 + size: 3109132 + timestamp: 1785913735357 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandoc-3.10.2-hce30654_0.conda + sha256: 086c2d905c861de43e8fefe128f68ca94ea9b9e8a476c310f9b2f12ffd713827 + md5: d17619f554a5892162869bec6f97a0c4 + license: GPL-2.0-or-later + license_family: GPL + purls: [] + run_exports: {} + size: 27215826 + timestamp: 1786704617167 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pcre2-10.47-he63d830_1.conda + sha256: f8c415329b542e1fca1ff2917b80e687c18302dfa0353530668b90cb225b494f + md5: 5ab90033816cbe4097e8a297e5179f67 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 + size: 851704 + timestamp: 1787294559157 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pillow-12.3.0-py314hab283cf_0.conda + sha256: dd7303ea135116cc1182c109825459a9eeb77d244d3899f03dd8d83a8db956f9 + md5: 4f25498ea1962ab24097fed8700e91ae + depends: + - python + - python 3.14.* *_cp314 + - __osx >=11.0 + - zlib-ng >=2.3.3,<2.4.0a0 + - openjpeg >=2.5.4,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libxcb >=1.17.0,<2.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - libwebp-base >=1.6.0,<2.0a0 + - python_abi 3.14.* *_cp314 + - tk >=8.6.13,<8.7.0a0 + - lcms2 >=2.19.1,<3.0a0 + license: HPND + purls: + - pkg:pypi/pillow?source=hash-mapping + run_exports: {} + size: 1019767 + timestamp: 1782912213683 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pixman-0.46.4-h784d473_3.conda + sha256: 4779cd57231ce2e96fac643fcbdd4a6f51a57986264545445574e9c4acf526d3 + md5: 9a99c0b60efe41c194d01c182d000733 + depends: + - __osx >=11.0 + - libcxx >=19 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 + size: 198717 + timestamp: 1786106922508 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314hd98292b_1.conda + sha256: 1cb01e783a9bcc350ecc1d80cbd207c0b0e1f60dc0db6ded8650e318796ba4bf + md5: bea6a028c9205ea3789bb38409cbfe43 + depends: + - python + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + purls: + - pkg:pypi/psutil?source=compressed-mapping + run_exports: {} + size: 242631 + timestamp: 1787417424394 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-h84a0fba_1003.conda + sha256: 1c2338b9b0486af86883b9593d2f3e2845bbf216ea453dfe5d9a228e8dbe4057 + md5: d4852e6054b74645cf49ca10f6349191 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 9238 + timestamp: 1786068031100 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.2.2-py314h63b12ec_0.conda + sha256: 18577d2164b23888bc4a6b78f1bdfa12efa7253bf0e3f871ccf49fda8d18acd8 + md5: a34643ba983b0d8aed611d7aab0233db + depends: + - __osx >=11.3 + - libffi >=3.7.0,<3.8.0a0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - setuptools + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyobjc-core?source=hash-mapping + run_exports: {} + size: 2183843 + timestamp: 1786667130341 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.2.2-py314hddd3963_0.conda + sha256: 4be5be6b7d204c4a18fa4eb679a0b2bc5136632df145ca4e8c22c3fae2f97b2e + md5: ac045b8c9dd989c9fcc86199fc68f7b1 + depends: + - __osx >=11.3 + - libffi >=3.7.0,<3.8.0a0 + - pyobjc-core 12.2.2.* + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyobjc-framework-cocoa?source=compressed-mapping + run_exports: {} + size: 382991 + timestamp: 1786682078806 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pytensor-3.3.0-py314h0ac4119_0.conda + sha256: 884da424d2d24f2f814422fb6da3904d8496772c77252f3e28ee05f0bfd02684 + md5: c0d7e06ae86b1159bdb14a5776dba730 + depends: + - python + - pytensor-base ==3.3.0 np2py314hdd732f0_0 + - clangxx + - blas * *accelerate + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 9843 + timestamp: 1786614456777 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pytensor-base-3.3.0-np2py314hdd732f0_0.conda + sha256: 3e1785ef7de319bde45ef29206ea416de87b958677ad45d919a70d5feecbed48 + md5: 409c5aebeacd76f31045c11dc4fd0e00 + depends: + - python + - setuptools >=59.0.0 + - scipy >=1,<2 + - numpy >=2.0 + - numba >=0.58,<=0.66.0 + - filelock >=3.15 + - python 3.14.* *_cp314 + - libcxx >=19 + - __osx >=11.0 + - numpy >=1.25,<3 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pytensor?source=hash-mapping + run_exports: {} + size: 3221853 + timestamp: 1786614456777 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.7-hf4d206d_100_cp314.conda + build_number: 100 + sha256: 2f07838e44942236471d84e2a99b603badde96e58f86cf78c38488d4da64353a + md5: 47bd7a90ff0aef0717323a94ba3a04a0 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.1,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.7,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 14159560 + timestamp: 1787154022633 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + sha256: 95f385f9606e30137cf0b5295f63855fd22223a4cf024d306cf9098ea1c4a252 + md5: dcf51e564317816cb8d546891019b3ab + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + run_exports: {} + size: 189475 + timestamp: 1770223788648 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.2.0-py312hcedbef1_0.conda + noarch: python + sha256: de17d16785e44ea075ba0912ad4618db3438a3cf79c13249b1646ac4e616ea35 + md5: 52d1e1fe1463e21e34be9b8c2bf6c96c + depends: + - python + - __osx >=11.0 + - libcxx >=21 + - _python_abi3_support 1.* + - cpython >=3.12 + - zeromq >=4.3.5,<4.4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=compressed-mapping + run_exports: {} + size: 195379 + timestamp: 1787301084171 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/qhull-2020.2-h420ef59_5.conda + sha256: 873ac689484262a51fd79bc6103c1a1bedbf524924d7f0088fb80703042805e4 + md5: 6483b1f59526e05d7d894e466b5b6924 + depends: + - __osx >=11.0 + - libcxx >=16 + license: LicenseRef-Qhull + purls: [] + run_exports: + weak: + - qhull >=2020.2,<2020.3.0a0 + size: 516376 + timestamp: 1720814307311 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda + sha256: d6782b430e6dce4fe8c7ac118cd988d5a193eb4a7f60741edfaede58016b6110 + md5: 9347fd56a002e6b58946831d48fe62f6 + depends: + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + run_exports: + weak: + - readline >=8.3,<9.0a0 + size: 314395 + timestamp: 1787033878899 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-2026.6.3-py314hc05cd11_0.conda + sha256: 7d4b49a7542735c63f0ef3379f83dfed1870a5d62ae4c3e357f859014fb1fcaf + md5: aa2a7e9c0ab5322b9bd6e75a384b48a1 + depends: + - python + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + run_exports: {} + size: 284937 + timestamp: 1787344325551 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/safetensors-0.8.0-py314h54f3292_0.conda + sha256: 39e617554a4863f954c12f9c73eb8a94d6168b64bcc99cfaa0e14a159a7004fa + md5: 7b6c8590d1cbd703205defdee8c7e8e8 + depends: + - python + - __osx >=11.0 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - __osx >=11.0 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/safetensors?source=hash-mapping + run_exports: {} + size: 480148 + timestamp: 1781179759890 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.18.0-py314h18e1515_0.conda + sha256: 7ce218a4e1c55775547835d21a7ead0d50e5ac348fd638ce6ba316c48c8547b7 + md5: e55fe08bb5d43e7120672338dd129030 + depends: + - __osx >=11.0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=19 + - libgfortran + - libgfortran5 >=14.3.0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.7 + - numpy >=1.23,<3 + - numpy >=2.0.0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scipy?source=hash-mapping + run_exports: {} + size: 14122215 + timestamp: 1781912992503 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda + sha256: 7efd6d7d18bf9cc5788bfe1c1e1620d9dbbe00a81c646814929a82ff31944cf3 + md5: a322c0a0d3b5be99ee11f9ccec99b60e + depends: + - __osx >=11.0 + - libsigtool 0.1.3 h98dc951_1 + - openssl >=3.5.7,<4.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 114653 + timestamp: 1786115093248 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.52-py314h5583935_0.conda + sha256: 9c86803397cf137bf92d517b6a4395d059cfb3dbfc1def708ed5963c5848db48 + md5: 61db956083da31d178a6940043d176d2 + depends: + - python + - greenlet !=0.4.17 + - typing-extensions >=4.6.0 + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/sqlalchemy?source=compressed-mapping + run_exports: {} + size: 4044830 + timestamp: 1786535242452 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_3.conda + sha256: 9f1cc109e6e57861110e9de6e03beca7fd2b7fbdb46124cccc07990b0844d88a + md5: 0676b8719dd1e9bb1003e59a481c6c3e + depends: + - libcxx >=19.0.0.a0 + - __osx >=11.0 + - ncurses >=6.6,<7.0a0 + license: NCSA + purls: [] + run_exports: {} + size: 200397 + timestamp: 1785906507697 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hbeba79b_4.conda + sha256: 857d89087ae7f2c328cf256728affcb7343031a148b4af847334d248a9cf564c + md5: 90a01bf394d1c594e0eb9258f967d828 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: TCL + purls: [] + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3342183 + timestamp: 1787272852357 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.8-py314h6c2aa35_0.conda + sha256: 4af8e4394d249619b4f1641c82fd6c0a8b97d51991ca2986095bed400c2e5eb9 + md5: ab1bd70ec9c95d199f8ce456823004ab + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + run_exports: {} + size: 922067 + timestamp: 1786227125229 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.1-py314h6c2aa35_0.conda + sha256: 09bfbee5a2bcf4df06f21a2aa9eb40a7af97864a569beb5ea85fd6baf6e03ce7 + md5: 4fffb3ba871bb05f34ffb705534dfef5 + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/unicodedata2?source=hash-mapping + run_exports: {} + size: 416130 + timestamp: 1770909728445 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/watchfiles-1.2.0-py314he1d1ac0_1.conda + sha256: cd8c788feb2a47551b7f37ca7dfa4b5df1fe732007539d29be53874f03c6d945 + md5: 042bf3289f21e8a5c28551d150704295 + depends: + - python + - anyio >=3.0.0 + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/watchfiles?source=hash-mapping + run_exports: {} + size: 352931 + timestamp: 1781180392615 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/websockets-17.0.1-py314h2fbedac_0.conda + sha256: 1c36aaa95a3fd57c3abd61903eac980403d944c0eee5c633206e1e9f49477fcf + md5: 27d17e43642cc45b5c771169cb386352 + depends: + - python + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/websockets?source=hash-mapping + run_exports: {} + size: 432578 + timestamp: 1785599301757 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-h84a0fba_2.conda + sha256: 5c5ea38ceec008e4ff40111fc166b04086fca310b0aa9e5bd46f65e6b0dcb71d + md5: 31d71ce1b056f69b6ec67ee0712bdf97 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxau >=1.0.12,<2.0a0 + size: 15124 + timestamp: 1786381585975 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-h84a0fba_2.conda + sha256: 2f6915f0897ace4a1b5d66d0463079f7bc9819b0048c03677e47764f0a743499 + md5: f51e9414bf1b7bb556aac1a0b74a75fe + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxdmcp >=1.1.5,<2.0a0 + size: 19486 + timestamp: 1786381546642 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h74c22ad_3.conda + sha256: 3e78c43207502418fc5fb2317bbbefe5df8b6fc1051d90bdcd1c881c76bb4193 + md5: 31cf6dcc138abe673c9440cd6fe6c6fe + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 + size: 77530 + timestamp: 1787228556857 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h10816f8_11.conda + sha256: 01fd50d2801b23b59fafea6bf704a6c5faf0f5969104400eae0e6572cb2e5304 + md5: d31c0e54c4f9c51100ec8c812ee925d1 + depends: + - libcxx >=19 + - __osx >=11.0 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.22,<1.0.23.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + run_exports: + weak: + - zeromq >=4.3.5,<4.4.0a0 + size: 245404 + timestamp: 1779124076307 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.3-h31dac16_1.conda + sha256: 489a29915a3e1b425cff4df10a448f55bbaaf29d777a0f8a9e381444e6a284f1 + md5: 4621ded2fd5b36f51454d5f81bff4ec1 + depends: + - __osx >=11.0 + - libcxx >=21 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - zlib-ng >=2.3.3,<2.4.0a0 + size: 95857 + timestamp: 1786737243497 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda + sha256: da867f5092eb0cb746d353694f0098031fd9817a4ce7d5743121209ae0f406ca + md5: 4ec2684c73812cc2c3d78379384a39cc + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 433687 + timestamp: 1786599629846 +- conda: https://conda.anaconda.org/conda-forge/win-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 8a1cee28bd0ee7451ada1cd50b64720e57e17ff994fc62dd8329bef570d382e4 + md5: 1626967b574d1784b578b52eaeb071e7 + depends: + - libgomp >=7.5.0 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + constrains: + - openmp_impl <0.0a0 + - msys2-conda-epoch <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 + size: 52252 + timestamp: 1770943776666 +- conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-26.1.0-py314h5a2d7ad_0.conda + sha256: 47917aa31232191136b40f3055d4b469c0a71475aea396c2413d753be014b7dc + md5: 6c4598c60f92421a0f9926a0f4b36dd0 + depends: + - cffi >=2.0.0b1 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=compressed-mapping + run_exports: {} + size: 33526 + timestamp: 1787248062135 +- conda: https://conda.anaconda.org/conda-forge/win-64/binutils_impl_win-64-2.46.1-default_ha84baeb_102.conda + sha256: 83476bc3ed6ee4f1d6e67e6e1360696a0ac3e99679f9c142674003cf721740e3 + md5: 7832bada38267be3333319febcf5e4fc + depends: + - ld_impl_win-64 2.46.1 default_hfd38196_102 + - m2w64-sysroot_win-64 >=12.0.0.r0 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + run_exports: {} + size: 6140284 + timestamp: 1784214565466 +- conda: https://conda.anaconda.org/conda-forge/win-64/blas-2.309-mkl.conda + build_number: 9 + sha256: 30951d77d5efea2977f644094fe67faf5f621d30f9aec669c6dd906769e5c637 + md5: df62249c6f2232ec771794699119d52e + depends: + - blas-devel 3.11.0 9*_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 18620 + timestamp: 1786059303886 +- conda: https://conda.anaconda.org/conda-forge/win-64/blas-devel-3.11.0-9_h85df5b5_mkl.conda + build_number: 9 + sha256: c319cafe77419a9fa9a049da6e132e7f4c90023c91f35c60ccfd254021f11a58 + md5: eaf7e91d72d60a3de4b2f8e218b517fb + depends: + - libblas 3.11.0 9_h8455456_mkl + - libcblas 3.11.0 9_h2a3cdd5_mkl + - liblapack 3.11.0 9_hf9ab0e9_mkl + - liblapacke 3.11.0 9_h3ae206f_mkl + - mkl >=2026.1.0,<2027.0a0 + - mkl-devel 2026.1.* + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 18169 + timestamp: 1786059259827 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-1.2.0-hc8c2fe1_3.conda + sha256: 85e12348d058791aabd6eeb6abc1d7ab44b8f6308f91c8475f44f778f2a158af + md5: 9eba56a007c44dc32d0b9d0a820871ea + depends: + - brotli-bin 1.2.0 hd477307_3 + - libbrotlidec 1.2.0 h84f9c24_3 + - libbrotlienc 1.2.0 he2a975b_3 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 20954 + timestamp: 1786622876247 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-bin-1.2.0-hd477307_3.conda + sha256: 5328e0576c729813d28efc15613f4be94d029d77c4fe5afda16cab0b8d0c9d05 + md5: dc04f7b3d82c6fb3fdf4d93e45b6ea2a + depends: + - libbrotlidec 1.2.0 h84f9c24_3 + - libbrotlienc 1.2.0 he2a975b_3 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 23119 + timestamp: 1786622866096 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314h85cf176_3.conda + sha256: f96c411313beb92a6a9066b823f7e8ea085f3e3889219b44306c44d59f99e611 + md5: b1ff58c1f0deedd3f25c103e37049cee + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hf02afa3_3 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + run_exports: {} + size: 336902 + timestamp: 1786623039339 +- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_10.conda + sha256: 04767466ee9227c9c57ab2c6503e0149177d34111c7418d2f420297acb1eb229 + md5: c3301c058362f340100d91cd8be0393f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + run_exports: + weak: + - bzip2 >=1.0.8,<2.0a0 + size: 55919 + timestamp: 1785906343696 +- conda: https://conda.anaconda.org/conda-forge/win-64/cairo-1.18.4-h477c42c_1.conda + sha256: 9ee4ad706c5d3e1c6c469785d60e3c2b263eec569be0eac7be33fbaef978bccc + md5: 52ea1beba35b69852d210242dd20f97d + depends: + - fontconfig >=2.15.0,<3.0a0 + - fonts-conda-ecosystem + - icu >=78.1,<79.0a0 + - libexpat >=2.7.3,<3.0a0 + - libfreetype >=2.14.1 + - libfreetype6 >=2.14.1 + - libglib >=2.86.3,<3.0a0 + - libpng >=1.6.53,<1.7.0a0 + - libzlib >=1.3.1,<2.0a0 + - pixman >=0.46.4,<1.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-only or MPL-1.1 + purls: [] + run_exports: + weak: + - cairo >=1.18.4,<2.0a0 + size: 1537783 + timestamp: 1766416059188 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.1.1-py314h5a2d7ad_2.conda + sha256: e0e10d676eb67a8a4c8991cec89fb6f150f919eb1266a1b39253a857b3dc0454 + md5: 672d6ff72c6265b25eeef94ce21e71ac + depends: + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=compressed-mapping + run_exports: {} + size: 346657 + timestamp: 1786775160153 +- conda: https://conda.anaconda.org/conda-forge/win-64/conda-gcc-specs-16.1.0-h851ee6d_3.conda + sha256: 0dfab7b5adecfbfd4093bf8251043cf71550051caadda228c6ecbfd40e5f42fc + md5: 700f080b26531379d9a8acb0f085352d + depends: + - gcc_impl_win-64 >=16.1.0,<16.1.1.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: {} + size: 47294 + timestamp: 1787333238012 +- conda: https://conda.anaconda.org/conda-forge/win-64/contourpy-1.3.3-py314hf309875_4.conda + sha256: f141bcbf8e490b49b2f53f517173d13a64d75e43cfae170e0d931cb0b66f4bce + md5: c26934035616f7d578f9da0491aed3d8 + depends: + - numpy >=1.25 + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/contourpy?source=hash-mapping + run_exports: {} + size: 247437 + timestamp: 1769155978556 +- conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.21-py314hb98de8c_0.conda + sha256: daa9397ffba6722f27c21b2f0a02b197f3ba9baedb484a155539743ec5ea3ac3 + md5: 945786ac874b8e821a675fbdd885f844 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + run_exports: {} + size: 4022782 + timestamp: 1780390190830 +- conda: https://conda.anaconda.org/conda-forge/win-64/double-conversion-3.4.0-hac47afa_0.conda + sha256: 09e30a170e0da3e9847d449b594b5e55e6ae2852edd3a3680e05753a5e015605 + md5: 3d3caf4ccc6415023640af4b1b33060a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - double-conversion >=3.4.0,<3.5.0a0 + size: 70943 + timestamp: 1765193243911 +- conda: https://conda.anaconda.org/conda-forge/win-64/fontconfig-2.18.3-hd47e2ca_1.conda + sha256: f26139e3c774a6434c8a73381c08e3d2a4c2f9d9ef9587c66aab8836211ee2ec + md5: ed95670fed91b091fe34ba6cae6677d7 + depends: + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libiconv >=1.18,<2.0a0 + - libintl >=0.22.5,<1.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - fontconfig >=2.18.3,<3.0a0 + - fonts-conda-ecosystem + size: 217988 + timestamp: 1786667461139 +- conda: https://conda.anaconda.org/conda-forge/win-64/freetype-2.14.3-h57928b3_2.conda + sha256: 32f7dd8ffe62fd485e9e6570e871f5be45af74c84fde62241a2417046a373efd + md5: 6fc6c09c05a099d58efd9b2e96598e41 + depends: + - libfreetype 2.14.3 h57928b3_2 + - libfreetype6 2.14.3 hdbac1cb_2 + - zlib + license: GPL-2.0-only OR FTL + purls: [] + run_exports: + weak: + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + size: 186945 + timestamp: 1786641050416 +- conda: https://conda.anaconda.org/conda-forge/win-64/fribidi-1.0.16-hfd05255_1.conda + sha256: 274b3e4ae5dff527062039d1dcb5cfdd9f91fa7d8eaf61358c09450b361385de + md5: 66f5ce9d0d618332023619a899ceb26f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - fribidi >=1.0.16,<2.0a0 + size: 65318 + timestamp: 1785912637725 +- conda: https://conda.anaconda.org/conda-forge/win-64/gcc-16.1.0-hb5e953d_3.conda + sha256: b0dba3638f794b0f2a737574d5544ba9102b4b542467ab2015beb58bb72a398d + md5: 2e2dd2ff89786b8c2087bb01d6906121 + depends: + - conda-gcc-specs + - gcc_impl_win-64 16.1.0 hf3f8c13_3 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 1351786 + timestamp: 1787333364390 +- conda: https://conda.anaconda.org/conda-forge/win-64/gcc_impl_win-64-16.1.0-hf3f8c13_3.conda + sha256: dc148f6b468b29192af93132e0ae4e5fcd2a71b184c3dc6d74edefa42abba860 + md5: cfe7e37706d5b7f392dd81bb354a84c0 + depends: + - binutils_impl_win-64 >=2.46.1 + - libgcc >=16.1.0 + - libgcc-devel_win-64 16.1.0 hecf7705_103 + - libgomp >=16.1.0 + - libstdcxx >=16.1.0 + - libstdcxx-devel_win-64 16.1.0 hc76ffd0_103 + - m2w64-sysroot_win-64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: {} + size: 65095791 + timestamp: 1787333099106 +- conda: https://conda.anaconda.org/conda-forge/win-64/graphite2-1.3.15-h5112557_1.conda + sha256: 93a59bdf944fb6f947bd7ad2f293d5d80db3a90f8ff8dfabc591e3752141e46f + md5: 79538e7a7bc024084eda5989f73fde35 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: LGPL-2.0-or-later + license_family: LGPL + purls: [] + run_exports: + weak: + - graphite2 >=1.3.15,<2.0a0 + size: 98064 + timestamp: 1786118492029 +- conda: https://conda.anaconda.org/conda-forge/win-64/greenlet-3.5.5-py314hb98de8c_0.conda + sha256: c1f9d4b92bf255fc5cc92ea10448d812417fd26132856cefe9f41f2d5ccc2f8a + md5: 212518796fa1c60ca92e4d1c8ef80ce3 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/greenlet?source=compressed-mapping + run_exports: {} + size: 259251 + timestamp: 1786384106710 +- conda: https://conda.anaconda.org/conda-forge/win-64/gxx-16.1.0-hb5e953d_3.conda + sha256: cdf3ad6ea0097cff6055ee110e205af38549d4a601d93ad156894474aabd3ed7 + md5: 60ae547baaf558222e923978f81f18b0 + depends: + - conda-gcc-specs + - gcc 16.1.0 hb5e953d_3 + - gxx_impl_win-64 16.1.0 he3d2c83_3 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 936148 + timestamp: 1787333412579 +- conda: https://conda.anaconda.org/conda-forge/win-64/gxx_impl_win-64-16.1.0-he3d2c83_3.conda + sha256: 60e8934bcd323f11af1a0181b193ca3a902d0db3c16b7eebc6db18a9a84ba2c7 + md5: ee6ef5218193fb363adc382738faf6a3 + depends: + - gcc_impl_win-64 16.1.0 hf3f8c13_3 + - libstdcxx-devel_win-64 16.1.0 hc76ffd0_103 + - m2w64-sysroot_win-64 + - tzdata + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: {} + size: 15850994 + timestamp: 1787333323014 +- conda: https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda + sha256: 75c549b55b673e15de8785a8e5dd85bca7eb612eee0ff4dc8d7bdaa15eacbdbb + md5: e596942e8ee6ee17fdcf1e6a77757a66 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - icu >=78.3,<79.0a0 + size: 16835644 + timestamp: 1784916416303 +- conda: https://conda.anaconda.org/conda-forge/win-64/kiwisolver-1.5.0-py314hf309875_0.conda + sha256: 37cbc49fd7255532d09fb3bc9cc699554693e632fa90678a9b3d0ed12557d0d7 + md5: 0508c8dabeab91311e5c59b5e3f6d278 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/kiwisolver?source=hash-mapping + run_exports: {} + size: 73330 + timestamp: 1773067062280 +- conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h719d79b_2.conda + sha256: 63ff03324e903eb01a715ccf357df56d66224e61952fd6615d86490ebefb3285 + md5: 93f5a01dec294a2228f757fe2f3432d4 + depends: + - openssl >=3.5.7,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - krb5 >=1.22.2,<1.23.0a0 + size: 753425 + timestamp: 1786762169034 +- conda: https://conda.anaconda.org/conda-forge/win-64/lcms2-2.19.1-hf2c6c5f_1.conda + sha256: 5ed63a32639a130564a870becb679fd52dfb816666a61ed3c023917389010480 + md5: 1df4012c8a2478699d07bc26af66d41e + depends: + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - lcms2 >=2.19.1,<3.0a0 + size: 523194 + timestamp: 1780211799997 +- conda: https://conda.anaconda.org/conda-forge/win-64/ld_impl_win-64-2.46.1-default_hfd38196_102.conda + sha256: e3cb27be096acab3c8d5ed36961e291e3e6e9c2323dd3fd565623a4c093e931c + md5: 179ed4e90a5c9560bebb28292a726f12 + depends: + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_win-64 2.46.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + run_exports: {} + size: 896485 + timestamp: 1784214548635 +- conda: https://conda.anaconda.org/conda-forge/win-64/lerc-4.2.0-hd936e49_0.conda + sha256: 93d666f63f284ef77b87b0b1f77b70f7d36d315a132f9afa64bc0012d937ba39 + md5: add59e2b60ac9d4299d17c938185c75a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - lerc >=4.2.0,<5.0a0 + size: 175297 + timestamp: 1785036247761 +- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-9_h8455456_mkl.conda + build_number: 9 + sha256: a99c640f10a3f77efe5c6605676ddc8d365d020eec4fdf1c803d34bdaf49b357 + md5: 17b26a4ad064259983bec1eaa36f40d3 + depends: + - mkl >=2026.1.0,<2027.0a0 + constrains: + - blas 2.309 mkl + - libcblas 3.11.0 9*_mkl + - liblapack 3.11.0 9*_mkl + - liblapacke 3.11.0 9*_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libblas >=3.11.0,<4.0a0 + size: 67235 + timestamp: 1786059219098 +- conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.2.0-hf02afa3_3.conda + sha256: c739589318a1f8a88cd1b66d385176fd1ec2c4609e9f90d23d748be94b547e4e + md5: 8ef4beb3cb18e1a876b9af9a757cc1a5 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlicommon >=1.2.0,<1.3.0a0 + size: 82655 + timestamp: 1786622832371 +- conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.2.0-h84f9c24_3.conda + sha256: f4bdb7ec97c3122e531fc867efae5ec928b649d047aa70d42893f0d8eb110fd9 + md5: 10c479888ee4e960587967b2d0c8143a + depends: + - libbrotlicommon 1.2.0 hf02afa3_3 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlidec >=1.2.0,<1.3.0a0 + size: 34788 + timestamp: 1786622843818 +- conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.2.0-he2a975b_3.conda + sha256: c5e638ea9704c94b316238b425a3439ba38d4d8fba81682842e6d7d464472848 + md5: cb5d08dc81f52e87c27914b5636cd995 + depends: + - libbrotlicommon 1.2.0 hf02afa3_3 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libbrotlienc >=1.2.0,<1.3.0a0 + size: 253894 + timestamp: 1786622854214 +- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-9_h2a3cdd5_mkl.conda + build_number: 9 + sha256: 8c20714bbb85c8a109e9002e76c32be64a82d9867beb1a35a20c85258cc2b535 + md5: 9d1d0c22e9ed8c31ec2efc0d063d6f48 + depends: + - libblas 3.11.0 9_h8455456_mkl + constrains: + - blas 2.309 mkl + - liblapack 3.11.0 9*_mkl + - liblapacke 3.11.0 9*_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libcblas >=3.11.0,<4.0a0 + size: 67587 + timestamp: 1786059232952 +- conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-22.1.8-default_hacd6ee9_9.conda + sha256: 4e6169971eaf472bfbdd9143202ccd5eed3a725c548155f42ebf3d19c9afea13 + md5: 20ec1bc1a4ff03f3a9098ad7b4d469b6 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - llvm-openmp >=22.1.8 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + - libxml2 + - libxml2-16 >=2.15.3 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + weak: + - libclang13 >=22.1.8 + size: 34915563 + timestamp: 1787349750337 +- conda: https://conda.anaconda.org/conda-forge/win-64/libdeflate-1.25-h1a1d4e4_1.conda + sha256: af1cda21d4653f594fbef20aa4e1ff158a546902b3307ef8af9a9b44b43862d2 + md5: e4e122e124676a49eebf241399ad8393 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libdeflate >=1.25,<1.26.0a0 + size: 157828 + timestamp: 1785908793271 +- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.8.1-hac47afa_1.conda + sha256: 1a54d874addda73b6f7164d5f3905821277a1831bcc05edd74b3085391688571 + md5: ccc490c81ffe14181861beac0e8f3169 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - expat 2.8.1.* + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 71631 + timestamp: 1781203724164 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.7.0-h3d046cb_0.conda + sha256: 2ea8d2fe7b84ca37653777e15ac1e7abd35f0c90d3efbe7f6c4de9b489606369 + md5: 92bdfc0e5012660892b0e0eaf3069a5c + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 50247 + timestamp: 1783521107166 +- conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype-2.14.3-h57928b3_2.conda + sha256: d794d7fddb6eea50e18a62fa27ab3819f40d51bad00b90cf4ca591fb0d4006c2 + md5: 740f99c3c91079c03874b809fedace1b + depends: + - libfreetype6 >=2.14.3 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: {} + size: 8742 + timestamp: 1786641045882 +- conda: https://conda.anaconda.org/conda-forge/win-64/libfreetype6-2.14.3-hdbac1cb_2.conda + sha256: cbc650854003e434d4ff6c7b1a2667e38a4242ad8a391a1c5ff89721624065ce + md5: 8157483eb7ed3fcba71aad3b50a97131 + depends: + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - freetype >=2.14.3 + license: GPL-2.0-only OR FTL + purls: [] + run_exports: {} + size: 340385 + timestamp: 1786641044865 +- conda: https://conda.anaconda.org/conda-forge/win-64/libgcc-16.1.0-h110b43a_3.conda + sha256: 125a3ea39e7308680a494416c5b8868bafefafc5f82987fae282c300614d979e + md5: e8d20d3561601e827dc754481294f40c + depends: + - _openmp_mutex >=4.5 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + constrains: + - libgcc-ng ==16.1.0=*_3 + - libgomp 16.1.0 h8ee18e1_3 + - msys2-conda-epoch <0.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: {} + size: 792903 + timestamp: 1787333031804 +- conda: https://conda.anaconda.org/conda-forge/win-64/libglib-2.88.3-he810d59_1.conda + sha256: fd94edec4f945c82ba6b983aae2bec21dd08209a5b387fb7a713534bb3db51af + md5: d8b3236ab45b58a0c4f4aa0a286cee13 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - pcre2 >=10.47,<10.48.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libintl >=0.22.5,<1.0a0 + - libiconv >=1.18,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - glib >2.66 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - libglib >=2.88.3,<3.0a0 + size: 4518977 + timestamp: 1786457672418 +- conda: https://conda.anaconda.org/conda-forge/win-64/libgomp-16.1.0-h8ee18e1_3.conda + sha256: 6ede93ef60404209453cddf8f1cae5b8d05dcc0c39e1021db1dace88db7543cf + md5: fa88e8a67d2f6370f7b3cd45e8861dfd + depends: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + constrains: + - msys2-conda-epoch <0.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: + strong: + - _openmp_mutex >=4.5 + - libgomp >=16.1.0 + size: 627339 + timestamp: 1787332971056 +- conda: https://conda.anaconda.org/conda-forge/win-64/libharfbuzz-14.3.1-h03b5201_0.conda + sha256: 79fa7b957cb1fa539b5be09a67872360e507a3f25501a0ceb26cda2b5091686e + md5: 72c117cd3215779e10bf16266db1d70e + depends: + - cairo >=1.18.4,<2.0a0 + - graphite2 >=1.3.15,<2.0a0 + - icu >=78.3,<79.0a0 + - libexpat >=2.8.1,<3.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libglib >=2.88.3,<3.0a0 + - libpng >=1.6.58,<1.7.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 1042074 + timestamp: 1786971066342 +- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.13.0-default_h049141e_1000.conda + sha256: 2ee12e37223dfcd0acd050c80a91150c482b6e2899198521e1800dce66662467 + md5: 6a01c986e30292c715038d2788aa1385 + depends: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - libxml2 + - libxml2-16 >=2.14.6 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libhwloc >=2.13.0,<2.13.1.0a0 + size: 2396128 + timestamp: 1770954127918 +- conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda + sha256: 35e04e3ddac7720fc7c550a1c9f998604299d6a7bd1f3ec9b2825d825061daa2 + md5: a8a2abdf0f901bc4779d9b7be0845921 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-only + purls: [] + run_exports: + weak: + - libiconv >=1.18,<2.0a0 + size: 694899 + timestamp: 1787033851701 +- conda: https://conda.anaconda.org/conda-forge/win-64/libintl-0.22.5-h5728263_3.conda + sha256: c7e4600f28bcada8ea81456a6530c2329312519efcf0c886030ada38976b0511 + md5: 2cf0cf76cc15d360dfa2f17fd6cf9772 + depends: + - libiconv >=1.17,<2.0a0 + license: LGPL-2.1-or-later + purls: [] + run_exports: + weak: + - libintl >=0.22.5,<1.0a0 + size: 95568 + timestamp: 1723629479451 +- conda: https://conda.anaconda.org/conda-forge/win-64/libjpeg-turbo-3.2.0-hfd05255_1.conda + sha256: df78ab4c0eecb3dd9331898f96baeed8e5ca1c363346332517abeb0b614b9a53 + md5: fc2c23bacefd1e733f1e1d6cd3b2aaeb + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - jpeg <0.0.0a + license: IJG AND BSD-3-Clause AND Zlib + purls: [] + run_exports: + weak: + - libjpeg-turbo >=3.2.0,<4.0a0 + size: 990125 + timestamp: 1785896494014 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-9_hf9ab0e9_mkl.conda + build_number: 9 + sha256: 62d0a7a70ee13c554d5d7ff94a2ba758c4111439822dcc81324dd4cfaf576071 + md5: bee6f13ab945c4034bdd0f722ad14dd5 + depends: + - libblas 3.11.0 9_h8455456_mkl + constrains: + - blas 2.309 mkl + - libcblas 3.11.0 9*_mkl + - liblapacke 3.11.0 9*_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - liblapack >=3.11.0,<3.12.0a0 + size: 79963 + timestamp: 1786059243440 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblapacke-3.11.0-9_h3ae206f_mkl.conda + build_number: 9 + sha256: 888dec7ff7b99ab912056090efc956d9042f6440069353f43dbbaadd26aa4cd2 + md5: 9f4598c34a84e78d4d6d5db97e7350f7 + depends: + - libblas 3.11.0 9_h8455456_mkl + - libcblas 3.11.0 9_h2a3cdd5_mkl + - liblapack 3.11.0 9_hf9ab0e9_mkl + constrains: + - blas 2.309 mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - liblapacke >=3.11.0,<3.12.0a0 + size: 84178 + timestamp: 1786059255731 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda + sha256: d36c4a1e1f80fd08e18a407e03622ff2f34dfdd022da6488ad19603dea19e6d5 + md5: 880a0c8549479b198af21ba5dc49b109 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + run_exports: + weak: + - liblzma >=5.8.3,<6.0a0 + size: 105809 + timestamp: 1786348717883 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_2.conda + sha256: f07e451de3db1836b87f7aedf95c8e65cdb06c0e6105329ba24bb5f7b5c75e2a + md5: 5ae92fd6614edd024576e14069d7ad4c + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 89109 + timestamp: 1786650384519 +- conda: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.58-hdc8cecf_1.conda + sha256: 8c49c32adf3ba2c59783630b82377f54ab72204ea99e2bafc90a47a8e25c1032 + md5: 5aa7348e73691187c81d51616f17e48a + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.2,<2.0a0 + license: zlib-acknowledgement + purls: [] + run_exports: + weak: + - libpng >=1.6.58,<1.7.0a0 + size: 385462 + timestamp: 1786616543374 +- conda: https://conda.anaconda.org/conda-forge/win-64/libraqm-0.11.0-h50d6d30_0.conda + sha256: 1bc52f781355e233411a7aaebbb155d9fd53efa2a1fc6c621250833d80cc5ab1 + md5: df92be5685f712989830bdb7ee39383a + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libharfbuzz >=14.2.1 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - fribidi >=1.0.16,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libraqm >=0.11.0,<0.12.0a0 + size: 33471 + timestamp: 1784850324004 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.22-h6a83c73_2.conda + sha256: 7dc8d243cc8bcd12d1666640664288822eda5d30411a0b22ff05090bbac4c32b + md5: 2a001157df8205a7785ea69dd3270a8f + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: ISC + purls: [] + run_exports: + weak: + - libsodium >=1.0.22,<1.0.23.0a0 + size: 280204 + timestamp: 1787225747847 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.4-hf5d6505_1.conda + sha256: 0a45d7c0f20146fff787a106f8fa187872e309c70975ff8f0936e188914c26ad + md5: a72d495965b144bb7da033642d389047 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: blessing + purls: [] + run_exports: + weak: + - libsqlite >=3.53.4,<4.0a0 + size: 1314919 + timestamp: 1787051140039 +- conda: https://conda.anaconda.org/conda-forge/win-64/libstdcxx-16.1.0-hae5796f_3.conda + sha256: 9beca52beac60dd9d3772a2ba73e78502c634b627e739560db54127aa34dd264 + md5: d830ed49961553edfb0445966d8334d5 + depends: + - libgcc 16.1.0 h110b43a_3 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + constrains: + - libstdcxx-ng ==16.1.0=*_3 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + run_exports: {} + size: 7153890 + timestamp: 1787333055619 +- conda: https://conda.anaconda.org/conda-forge/win-64/libtiff-4.7.2-h8f73337_0.conda + sha256: ec6d66308a6d6abaf3225f2f185113e6172e77eb0fa8622af982d7a5d6d47a2c + md5: e83f459471905a04ebe15e21d063c49d + depends: + - lerc >=4.1.0,<5.0a0 + - libdeflate >=1.25,<1.26.0a0 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: HPND + purls: [] + run_exports: + weak: + - libtiff >=4.7.2,<4.8.0a0 + size: 1014598 + timestamp: 1783085017197 +- conda: https://conda.anaconda.org/conda-forge/win-64/libvulkan-loader-1.4.357.0-h477610d_2.conda + sha256: 4b094443126c5fc38d200eb0ea335b67e64d966d7aa737bb3141217a787b0c73 + md5: aaeed7feddbfd7454f8853a5eae8d902 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + constrains: + - libvulkan-headers 1.4.357.0.* + license: Apache-2.0 + purls: [] + run_exports: + weak: + - libvulkan-loader >=1.4.357.0,<2.0a0 + size: 288787 + timestamp: 1787491929908 +- conda: https://conda.anaconda.org/conda-forge/win-64/libwebp-base-1.6.0-h4d5522a_1.conda + sha256: 4470d98d3178b0d45492eed4808afe421d2e7808352b8d06c2dc29166b75d94d + md5: 35a9475e4cc999d52921f57c181979fc + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libwebp 1.6.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libwebp-base >=1.6.0,<2.0a0 + size: 278886 + timestamp: 1785954716703 +- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + sha256: 0fccf2d17026255b6e10ace1f191d0a2a18f2d65088fd02430be17c701f8ffe0 + md5: 8a86073cf3b343b87d03f41790d8b4e5 + depends: + - ucrt + constrains: + - pthreads-win32 <0.0a0 + - msys2-conda-epoch <0.0a0 + license: MIT AND BSD-3-Clause-Clear + purls: [] + run_exports: {} + size: 36621 + timestamp: 1759768399557 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxcb-1.17.0-h874e120_1.conda + sha256: a99f266ade1140c3106cca0f71ae2b5627ff77e1e791db3837129d28d596800e + md5: 98046512ad7f2c44e48ff77bce854052 + depends: + - libgcc >=13 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - pthread-stubs + - ucrt >=10.0.20348.0 + - xorg-libxau >=1.0.12,<2.0a0 + - xorg-libxdmcp >=1.1.5,<2.0a0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxcb >=1.17.0,<2.0a0 + size: 1218652 + timestamp: 1787077697863 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h3cfd58e_1.conda + sha256: 8163de24a7ddb4ebf9587c3a45ba950caf3690b9646b76f007ca15e6e52b5881 + md5: 6e7dadff3f3bde2d29d29a3ec34f2d58 + depends: + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libxml2 2.15.3 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 519962 + timestamp: 1787237653321 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-h8ef44ab_1.conda + sha256: a83e9adcf7c50f20289dc6890707c8e4e84151b4204b0f7344998138807458d1 + md5: 45a5a1c709a69f14cf176220788d18a9 + depends: + - icu >=78.3,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.3,<6.0a0 + - libxml2-16 2.15.3 h3cfd58e_1 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxml2 + - libxml2-16 >=2.15.3 + size: 43610 + timestamp: 1787237661577 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxslt-1.1.43-h0fbe4c1_1.conda + sha256: 13da38939c2c20e7112d683ab6c9f304bfaf06230a2c6a7cf00359da1a003ec7 + md5: 46034d9d983edc21e84c0b36f1b4ba61 + depends: + - libxml2 + - libxml2-16 >=2.14.6 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libxslt >=1.1.43,<2.0a0 + size: 420223 + timestamp: 1757963935611 +- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda + sha256: 0629c2cc0404d3bb29d6baa7b4ba62da80797015e86de050db81ea5a07050527 + md5: 5d2ff29d465097458cc3ff6569151991 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - zlib 1.3.2 *_3 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 58529 + timestamp: 1785276664143 +- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.8-h4fa8253_1.conda + sha256: 41a804136fdade8cfa9db006f3c41cac1199a387e609c465d779cef271fda85e + md5: 8135c070cad2ee5bb28ea50c12e81ce9 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - intel-openmp <0.0a0 + - openmp 22.1.8|22.1.8.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + run_exports: + strong: + - llvm-openmp >=22.1.8 + size: 348946 + timestamp: 1787293654028 +- conda: https://conda.anaconda.org/conda-forge/win-64/llvmlite-0.48.0-py314h46b4103_1.conda + sha256: 62f997491572f3b83301b64a0056bba0e77db5a6612a3f9acf3876c3c830d963 + md5: b4006e5a63ca3f2d825a079712ff067e + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + - zstd >=1.5.7,<1.6.0a0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/llvmlite?source=hash-mapping + run_exports: {} + size: 28574162 + timestamp: 1784043479652 +- conda: https://conda.anaconda.org/conda-forge/win-64/m2-conda-epoch-20250515-0_x86_64.conda + build_number: 0 + sha256: 51e9214548f177db9c3fe70424e3774c95bf19cd69e0e56e83abe2e393228ba1 + md5: 7d60fb16df2cd07fbc3dbff1c9df4244 + constrains: + - msys2-conda-epoch <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - m2-conda-epoch 20250515 *_x86_64 + noarch: + - m2-conda-epoch 20250515 *_x86_64 + size: 7539 + timestamp: 1747330852019 +- conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + sha256: 02805a0f3cd168dbf13afc5e4aed75cc00fe538ce143527a6471485b36f5887c + md5: 8de7b40f8b30a8fcaa423c2537fe4199 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + run_exports: {} + size: 30022 + timestamp: 1772445159549 +- conda: https://conda.anaconda.org/conda-forge/win-64/matplotlib-3.11.1-py314h30c6bc1_2.conda + sha256: 3599b3ae70c4fd210e83d3e04920b70e763a3c3cc6a589f7a46776a339cf79c0 + md5: d8f7f4bb221698dda04dd955eb6f7e52 + depends: + - matplotlib-base >=3.11.1,<3.11.2.0a0 + - pyside6 >=6.7.2 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - tornado >=5 + license: PSF-2.0 + license_family: PSF + purls: [] + run_exports: {} + size: 15333 + timestamp: 1785211311397 +- conda: https://conda.anaconda.org/conda-forge/win-64/matplotlib-base-3.11.1-py314h2061cd4_2.conda + sha256: b3f19b71ea556c79b67a599929a4c05618fd4ae03d7412e65adc95ec627670c5 + md5: 88c095cee1bcd48178328c93920870a2 + depends: + - contourpy >=1.0.1 + - cycler >=0.10 + - fonttools >=4.28.2 + - freetype + - kiwisolver >=1.3.1 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libraqm >=0.11.0,<0.12.0a0 + - numpy >=1.25 + - numpy >=1.25,<3 + - packaging >=20.0 + - pillow >=9 + - pyparsing >=3 + - python >=3.14,<3.15.0a0 + - python-dateutil >=2.7 + - python_abi 3.14.* *_cp314 + - qhull >=2020.2,<2020.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/matplotlib?source=hash-mapping + run_exports: {} + size: 8810362 + timestamp: 1785211292854 +- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2026.1.0-hac47afa_234.conda + sha256: f7568a5ebf9f4a401a6d9da7be4f82a8794cf305e870e77923a5712ba7f4b964 + md5: f0510f9d5e501462d72a5c0c798dbcc3 + depends: + - llvm-openmp >=22.1.8 + - tbb >=2023.0.0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + run_exports: {} + size: 114429478 + timestamp: 1786086389935 +- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-devel-2026.1.0-h57928b3_234.conda + sha256: 1a7fcabf40552d35fd9ed5be0759ad129e0db56867fb3ab816beff1263b015bb + md5: 9adca581ae34f78252ca387128707ea3 + depends: + - mkl 2026.1.0 hac47afa_234 + - mkl-include 2026.1.0 h57928b3_234 + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + run_exports: + weak: + - mkl >=2026.1.0,<2027.0a0 + size: 5448461 + timestamp: 1786086741635 +- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-include-2026.1.0-h57928b3_234.conda + sha256: cf7d6f4cb879d4066c7ddcbc7795a6e6a993d538a417b0f838819b17d048ec61 + md5: 089c701d8617a906df5afd076a1daffa + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + run_exports: {} + size: 793957 + timestamp: 1786086608942 +- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-service-2.8.0-py314h6d79c4c_0.conda + sha256: e8486ba8a4ae490bbb343c20866b55230aaf07ffa5820e8477d894929daf0299 + md5: 6a0b559d040714f2d90b3bf1ca6c15a0 + depends: + - mkl >=2026.1.0,<2027.0a0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/mkl-service?source=hash-mapping + run_exports: {} + size: 65912 + timestamp: 1785145741824 +- conda: https://conda.anaconda.org/conda-forge/win-64/numba-0.66.0-py314hb98de8c_1.conda + sha256: aca94d88bdde53f633e4264202c8516d664f4d156e476c7a046cb7bf64ba0957 + md5: 3f1b4917ec0f902bba25c6dd0e5a348a + depends: + - python + - llvmlite >=0.48.0,<0.49.0a0 + - numpy >=1.22.3,<2.5 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - numpy >=1.23,<3 + - python_abi 3.14.* *_cp314 + constrains: + - tbb >=2021.6.0 + - libopenblas !=0.3.6 + - cuda-version >=11.2 + - cudatoolkit >=11.2 + - scipy >=1.0 + - cuda-python >=11.6 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/numba?source=hash-mapping + run_exports: {} + size: 6178278 + timestamp: 1785940762943 +- conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.4.6-py314h02f10f6_0.conda + sha256: de0eee21d902fb45a58454e3739e04ede7d02bf7575ca0ae9f959f20fa15c76b + md5: df95e6c7325bbae2571e5cef5f9c8096 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - libblas >=3.9.0,<4.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + run_exports: + weak: + - numpy >=1.23,<3 + size: 7318163 + timestamp: 1779169232086 +- conda: https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.5.4-h0e57b4f_0.conda + sha256: 24342dee891a49a9ba92e2018ec0bde56cc07fdaec95275f7a55b96f03ea4252 + md5: e723ab7cc2794c954e1b22fde51c16e4 + depends: + - libpng >=1.6.55,<1.7.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - openjpeg >=2.5.4,<3.0a0 + size: 245594 + timestamp: 1772624841727 +- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.3-hf411b9b_1.conda + sha256: 2ebff5a1b5793e82495bf33c91fba040e11ff23333c2385ac66d0c3aee2cc14c + md5: a978392692a910ba1c8920ccb1e784b3 + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: [] + run_exports: + weak: + - openssl >=3.6.3,<4.0a0 + size: 9427535 + timestamp: 1785915614585 +- conda: https://conda.anaconda.org/conda-forge/win-64/pandoc-3.10.2-h57928b3_0.conda + sha256: afcb977d62149f0e0c7f946e50f29a0b7ac24ef04c6d11b29478ea11dd63d825 + md5: 7643f65d7e954c60f69b353ae536730a + license: GPL-2.0-or-later + license_family: GPL + purls: [] + run_exports: {} + size: 26943591 + timestamp: 1786704423753 +- conda: https://conda.anaconda.org/conda-forge/win-64/pcre2-10.47-h8466c1e_1.conda + sha256: d8e9ea26b52a09d880d1e5371830c8dd5b4c099a6db64dbdf8236440744b7499 + md5: 009af999dbe2d1db36a37187a4ca4eb4 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libzlib >=1.3.2,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - pcre2 >=10.47,<10.48.0a0 + size: 993241 + timestamp: 1787294653206 +- conda: https://conda.anaconda.org/conda-forge/win-64/pillow-12.3.0-py314h61b30b5_0.conda + sha256: c9dc3212ed0021974541072ee3765a5097a0721191c34ee485d7d7e94449648f + md5: 09b8e6ac8f4a257b59e5d3025f3c9c1d + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libwebp-base >=1.6.0,<2.0a0 + - libtiff >=4.7.1,<4.8.0a0 + - openjpeg >=2.5.4,<3.0a0 + - lcms2 >=2.19.1,<3.0a0 + - libxcb >=1.17.0,<2.0a0 + - libjpeg-turbo >=3.1.4.1,<4.0a0 + - tk >=8.6.13,<8.7.0a0 + - zlib-ng >=2.3.3,<2.4.0a0 + license: HPND + purls: + - pkg:pypi/pillow?source=hash-mapping + run_exports: {} + size: 989058 + timestamp: 1782912129930 +- conda: https://conda.anaconda.org/conda-forge/win-64/pixman-0.46.4-h5112557_3.conda + sha256: cad8b94c2b00264a15d469eed6dc53aac1c59c6d46f27ad1d91bfaf227cf136a + md5: 27c5be39d9e4d25fe85b89a069360d1e + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - pixman >=0.46.4,<1.0a0 + size: 257473 + timestamp: 1786106677325 +- conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_1.conda + sha256: c975e08da7627e95d1f0b70ef9787e9153118e67bb5b31f5530c5c3827d9afe8 + md5: deeef9494cfffa58f5fd20bc6eb57664 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + purls: + - pkg:pypi/psutil?source=hash-mapping + run_exports: {} + size: 249966 + timestamp: 1787417377436 +- conda: https://conda.anaconda.org/conda-forge/win-64/pthread-stubs-0.4-hba3369d_1003.conda + sha256: 5546927a2e337d2903d6cdb028fb33723cdbcc45bf9abe1770fbde2c4ea8bce6 + md5: bc97d497656c9c661ffd3043aca90aa4 + depends: + - libgcc >=14 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 10120 + timestamp: 1786067833280 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyside6-6.11.2-py314h447aaf0_0.conda + sha256: bf1553eebc31e8ba04689639e8ce235c3df5317414f0c4a11417f238297f1b17 + md5: 7c3ccff96dbc9f8e3c40142c7594ec34 + depends: + - python + - qt6-main 6.11.2.* + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libxml2 + - libxml2-16 >=2.14.6 + - libclang13 >=22.1.8 + - qt6-main >=6.11.2,<7.0a0 + - python_abi 3.14.* *_cp314 + - libvulkan-loader >=1.4.357.0,<2.0a0 + - libxslt >=1.1.43,<2.0a0 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/pyside6?source=hash-mapping + - pkg:pypi/shiboken6?source=hash-mapping + run_exports: {} + size: 11552286 + timestamp: 1787219450026 +- conda: https://conda.anaconda.org/conda-forge/win-64/pytensor-3.3.0-py314h443d124_0.conda + sha256: afc5e3836f2886eff9e5035ddb518acd07ef62f89c1e72fa1df8eddfbbe3feab + md5: 731852fdc6b3a561afed885eaa929e57 + depends: + - python + - pytensor-base ==3.3.0 np2py314hb7a55bc_0 + - gxx + - blas * mkl + - mkl-service + - python_abi 3.14.* *_cp314 + constrains: + - libstdcxx !=15.1.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 10069 + timestamp: 1786614345920 +- conda: https://conda.anaconda.org/conda-forge/win-64/pytensor-base-3.3.0-np2py314hb7a55bc_0.conda + sha256: cd2fae7ea29d751cecfd82eeaa21c83cdb6d83c5ed159ffac98c0522bbd8121b + md5: f77cc243811952111800a5e6b8816324 + depends: + - python + - setuptools >=59.0.0 + - scipy >=1,<2 + - numpy >=2.0 + - numba >=0.58,<=0.66.0 + - filelock >=3.15 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - numpy >=1.25,<3 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pytensor?source=hash-mapping + run_exports: {} + size: 3232733 + timestamp: 1786614345920 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.7-h53f6dd8_100_cp314.conda + build_number: 100 + sha256: 01cd1d39e5a24f029df0a8db0878dd442d552a82f584e18fd2ed366bc881633f + md5: 99dcbb9c65cb1fb10340bc7f6984ddfa + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.8.1,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.53.4,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.7,<4.0a0 + - python_abi 3.14.* *_cp314 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + run_exports: + weak: + - python_abi 3.14.* *_cp314 + noarch: + - python + size: 18052663 + timestamp: 1787154783216 + python_site_packages_path: Lib/site-packages +- conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-312-py314hf700ef7_1.conda + sha256: 5a6ddd03a8441c2312a09f998dccb0bdeb1b906b45c9b8cd5e9f5a7965b0a604 + md5: 57992821d70e28562192fa29cff08260 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/pywin32?source=hash-mapping + run_exports: {} + size: 4473050 + timestamp: 1787374336870 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-3.0.5-py314h51f0985_0.conda + sha256: 025a42fa3df042590f9f5efdf8473e98e654672871c9db029436f32e021cb900 + md5: 9f34ac4f934a5e6bdffa81db44b3ce82 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - winpty + license: MIT + license_family: MIT + purls: + - pkg:pypi/pywinpty?source=hash-mapping + run_exports: {} + size: 731340 + timestamp: 1785742446062 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + sha256: a2aff34027aa810ff36a190b75002d2ff6f9fbef71ec66e567616ac3a679d997 + md5: 0cd9b88826d0f8db142071eb830bce56 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + run_exports: {} + size: 181257 + timestamp: 1770223460931 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.2.0-py312h343a6d4_0.conda + noarch: python + sha256: 56d33fdddf6fb7ffb86120b8e2f1398cc406d0d3e85e5647d3a72cad05c17509 + md5: 58bcf20b110e99aa69ab892a6ced10f5 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - _python_abi3_support 1.* + - cpython >=3.12 + - zeromq >=4.3.5,<4.3.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=compressed-mapping + run_exports: {} + size: 187939 + timestamp: 1787300948668 +- conda: https://conda.anaconda.org/conda-forge/win-64/qhull-2020.2-hc790b64_5.conda + sha256: 887d53486a37bd870da62b8fa2ebe3993f912ad04bd755e7ed7c47ced97cbaa8 + md5: 854fbdff64b572b5c0b470f334d34c11 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: LicenseRef-Qhull + purls: [] + run_exports: + weak: + - qhull >=2020.2,<2020.3.0a0 + size: 1377020 + timestamp: 1720814433486 +- conda: https://conda.anaconda.org/conda-forge/win-64/qt6-main-6.11.2-pl5321hfcac499_0.conda + sha256: 042c94a5a7a89b0b28a24f6ae6a2d3d609751edab78454057973ec5cc3e77d7d + md5: d98a163070d05c6ed4421432ee1bafb8 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libvulkan-loader >=1.4.357.0,<2.0a0 + - icu >=78.3,<79.0a0 + - libfreetype >=2.14.3 + - libfreetype6 >=2.14.3 + - libharfbuzz >=14.3.1 + - libzlib >=1.3.2,<2.0a0 + - double-conversion >=3.4.0,<3.5.0a0 + - libglib >=2.88.3,<3.0a0 + - krb5 >=1.22.2,<1.23.0a0 + - pcre2 >=10.47,<10.48.0a0 + - libpng >=1.6.58,<1.7.0a0 + - zstd >=1.5.7,<1.6.0a0 + - libsqlite >=3.53.4,<4.0a0 + - openssl >=3.5.7,<4.0a0 + - libjpeg-turbo >=3.2.0,<4.0a0 + - libtiff >=4.7.2,<4.8.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libwebp-base >=1.6.0,<2.0a0 + constrains: + - qt ==6.11.2 + license: LGPL-3.0-only + license_family: LGPL + purls: [] + run_exports: + weak: + - qt6-main >=6.11.2,<7.0a0 + size: 89682645 + timestamp: 1787049046883 +- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-2026.6.3-py314h9f07db2_0.conda + sha256: d297e7ef5f062194cf76dcf7a2e0449af24012b895a06aa942805f2933a0256c + md5: 07602f253d1ad9436bcac564c9fe183f + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=compressed-mapping + run_exports: {} + size: 218916 + timestamp: 1787344535083 +- conda: https://conda.anaconda.org/conda-forge/win-64/safetensors-0.8.0-py314h9f07db2_0.conda + sha256: 096520c49c0ab0aa78935e54d8e5141bc01cc4a37eacb4d72e21ac5755e33631 + md5: 327246b3f9b6d7f95a0713b4d68b7cd4 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/safetensors?source=hash-mapping + run_exports: {} + size: 359273 + timestamp: 1781179723506 +- conda: https://conda.anaconda.org/conda-forge/win-64/scipy-1.18.0-py314h221f224_0.conda + sha256: 952db1642d707d2572b511b1207bfd8e8c114fdc99930c400b547eb8ab92ac19 + md5: a925cfb1429da2b1312c86516ae7c418 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - numpy <2.7 + - numpy >=1.23,<3 + - numpy >=2.0.0 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scipy?source=hash-mapping + run_exports: {} + size: 15353018 + timestamp: 1781914001107 +- conda: https://conda.anaconda.org/conda-forge/win-64/sqlalchemy-2.0.52-py314hc5dbbe4_0.conda + sha256: d3ab49c60febcc9edd55ec7f65a9e02b631e137fe609643c590e8151becacca7 + md5: caa67c9335b6f97b708186a6474a306b + depends: + - python + - greenlet !=0.4.17 + - typing-extensions >=4.6.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/sqlalchemy?source=hash-mapping + run_exports: {} + size: 3998837 + timestamp: 1786535220662 +- conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2023.0.0-hd3d4ead_2.conda + sha256: 8a4053839b8e997a5965e2dff7d6cf3c77be62d82c0e48c8a04a5ed2d2e73035 + md5: 8ee01a693aecff5432069eaaf1183c45 + depends: + - libhwloc >=2.13.0,<2.13.1.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: APACHE + purls: [] + run_exports: {} + size: 156515 + timestamp: 1778673901757 +- conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h967ab96_4.conda + sha256: f19618a3a82cc483dacf1c70a30367ee7b0c7e71b90f1f80e14feff44fbd3688 + md5: dd9eb33c99d352b6356f86964d6040f7 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: TCL + purls: [] + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3782376 + timestamp: 1787272860855 +- conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.8-py314h5a2d7ad_0.conda + sha256: 1cac25c190b60a4b6fbe2853c4989a4ce086564ee5f995c17d4b32885993068d + md5: 94dfb208db7d79437cfe9b4390706b5c + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + run_exports: {} + size: 925990 + timestamp: 1786226866739 +- conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 + md5: 71b24316859acd00bdb8b38f5e2ce328 + constrains: + - vc14_runtime >=14.29.30037 + - vs2015_runtime >=14.29.30037 + license: LicenseRef-MicrosoftWindowsSDK10 + purls: [] + run_exports: {} + size: 694692 + timestamp: 1756385147981 +- conda: https://conda.anaconda.org/conda-forge/win-64/unicodedata2-17.0.1-py314h5a2d7ad_0.conda + sha256: 9041e463044944460f73f9528f2ec491180f0ffe857e3555aa8160b81050b8d9 + md5: d6b580a13384df5155c6ca19ee66854e + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/unicodedata2?source=hash-mapping + run_exports: {} + size: 406126 + timestamp: 1770909191618 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.5-ha367084_41.conda + sha256: 35444c55a92e2f7f7ba26bc70f81e56e52344f7d064c0fd4b40a46a58517b79c + md5: aa805b5522c2a98fa286e551a1f48546 + depends: + - vc14_runtime >=14.51.36247 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 21383 + timestamp: 1785359368566 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.51.36247-habf1de7_41.conda + sha256: 4e4cb599cdc41bf2109d1464c127b5bcbddf548ce3e322e612afb691338b48f8 + md5: ac5333bb3d429361f23adf704cc49a78 + depends: + - ucrt >=10.0.20348.0 + - vcomp14 14.51.36247 habf1de7_41 + constrains: + - vs2015_runtime 14.51.36247.* *_41 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + run_exports: {} + size: 767955 + timestamp: 1785359364369 +- conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.51.36247-habf1de7_41.conda + sha256: 731e043390c9457299484d39e427221fc868a9249540a498a5a4f6456c7744d1 + md5: 350bb67a5c8e5f1c53347ac544ab6600 + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.51.36247.* *_41 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + run_exports: + strong: + - vcomp14 >=14.51.36247 + size: 155910 + timestamp: 1785359349999 +- conda: https://conda.anaconda.org/conda-forge/win-64/watchfiles-1.2.0-py314hc980628_1.conda + sha256: 262150bdbbecbe49096ef90b8233412d6134f4d43168e7e5c530d8b3252f6cb4 + md5: 5654b0a18935e2baecb89e33e2d6a530 + depends: + - python + - anyio >=3.0.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/watchfiles?source=hash-mapping + run_exports: {} + size: 351309 + timestamp: 1781180337205 +- conda: https://conda.anaconda.org/conda-forge/win-64/websockets-17.0.1-py314h13f4da2_0.conda + sha256: 67ed3e8abf94be2a1447e19d490afdba9037aa84f4f29930d791888d3ec6bb35 + md5: 8cf9a416e9e7c87b9687508a30245398 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/websockets?source=hash-mapping + run_exports: {} + size: 487341 + timestamp: 1785597313208 +- conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + sha256: 9df10c5b607dd30e05ba08cbd940009305c75db242476f4e845ea06008b0a283 + md5: 1cee351bf20b830d991dbe0bc8cd7dfe + license: MIT + license_family: MIT + purls: [] + run_exports: {} + size: 1176306 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_2.conda + sha256: 892ad69b1a9ecc3903ed5a1b18fa097013eaf462eeed3c6ff31bf5c12e71e84b + md5: 87aee04978ab77bf4c0f42b983c216cc + depends: + - libgcc >=14 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxau >=1.0.12,<2.0a0 + size: 110446 + timestamp: 1786381242485 +- conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxdmcp-1.1.5-hba3369d_2.conda + sha256: 21b11bb98c41ece4ce6069d86d826b50b3d73020fb631b97e59a0521dd9d08a1 + md5: 0e21a45f1bb429b6e35e82631e60554a + depends: + - libgcc >=14 + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - xorg-libxdmcp >=1.1.5,<2.0a0 + size: 71362 + timestamp: 1786381239727 +- conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + sha256: 80ee68c1e7683a35295232ea79bcc87279d31ffeda04a1665efdb43cbd50a309 + md5: 433699cba6602098ae8957a323da2664 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - yaml >=0.2.5,<0.3.0a0 + size: 63944 + timestamp: 1753484092156 +- conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h3a581c9_11.conda + sha256: c3e279cb309b153152fcdd6ee6d039ad996d563c849f06be39d85b8e3351df25 + md5: f016c0c5f9c01549b259146614786192 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libsodium >=1.0.22,<1.0.23.0a0 + - krb5 >=1.22.2,<1.23.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + run_exports: + weak: + - zeromq >=4.3.5,<4.3.6.0a0 + size: 265717 + timestamp: 1779124031378 +- conda: https://conda.anaconda.org/conda-forge/win-64/zlib-1.3.2-hfd05255_3.conda + sha256: 5a0b55df66ff07b4342e04967cef69f8bf348f6a0fb1cc1eca741c7b015dfe77 + md5: 945092a9bc1d0f250f7d5ecf51ecd471 + depends: + - libzlib 1.3.2 hfd05255_3 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - libzlib >=1.3.2,<2.0a0 + size: 851288 + timestamp: 1785276674755 +- conda: https://conda.anaconda.org/conda-forge/win-64/zlib-ng-2.3.3-h0261ad2_1.conda + sha256: 71332532332d13b5dbe57074ddcf82ae711bdc132affa5a2982a29ffa06dc234 + md5: 46a21c0a4e65f1a135251fc7c8663f83 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Zlib + license_family: Other + purls: [] + run_exports: + weak: + - zlib-ng >=2.3.3,<2.4.0a0 + size: 124542 + timestamp: 1770167984883 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda + sha256: ca7daae4f218a11fab82cc2857f0ea518ec3f46acec60490485347a4c22c6b3e + md5: e4ac308c39d6d0e131154976da67cf3b + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.2,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - zstd >=1.5.7,<1.6.0a0 + size: 387535 + timestamp: 1786599623274 +- pypi: . + name: pytensor-ml + requires_dist: + - numpy + - pytensor>=3.2.3,<4.0.0 + - safetensors + - jax ; extra == 'dev' + - mypy ; extra == 'dev' + - pre-commit ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pyyaml ; extra == 'dev' + - scikit-learn ; extra == 'dev' + - matplotlib ; extra == 'examples' + - tqdm ; extra == 'examples' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/01/a4/9b63d595d748e3aff8812b65eacc1a2c4bd90b7c2012e08e72373b4835eb/filelock-3.32.4-py3-none-any.whl + name: filelock + version: 3.32.4 + sha256: 22e58ca3b1ae3b98993b762d7338367ae64fe50252bf78d59da3bfebcdf1cedd + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/0f/26/885774c006de6620ed3d10f45d8e20fe0b8e6aad6d573211a2cbc8b3e528/numba-0.66.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: numba + version: 0.66.0 + sha256: e2b101f23b8b63978d334574d2039f27f0dccfe1d891756f33a2e2f3e4c88cf4 + requires_dist: + - llvmlite>=0.48.0.dev0,<0.49 + - numpy>=1.22,<2.5 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/15/4d/0eae213c5197c6a0cb4080f984c7295cb53af6d0ecba9ece190a6ae9560f/pytensor-3.3.0-cp314-cp314-win_amd64.whl + name: pytensor + version: 3.3.0 + sha256: 115ce884c378a476397071c07c3de228b6defbf064de0ccca8a8ebf369093b74 + requires_dist: + - setuptools>=59.0.0 + - scipy>=1,<2 + - numpy>=2.0 + - numba>=0.58,<=0.66.0 + - filelock>=3.15 + - pytensor[jax] ; extra == 'complete' + - pytensor[numba] ; extra == 'complete' + - pytensor[complete] ; extra == 'development' + - pytensor[tests] ; extra == 'development' + - pytensor[rtd] ; extra == 'development' + - pytest ; extra == 'tests' + - pre-commit ; extra == 'tests' + - pytest-cov>=2.6.1 ; extra == 'tests' + - coverage>=5.1 ; extra == 'tests' + - pytest-benchmark ; extra == 'tests' + - pytest-mock ; extra == 'tests' + - pytest-sphinx ; extra == 'tests' + - pytensor[kanren] ; extra == 'tests' + - sphinx>=5.1.0,<6 ; extra == 'rtd' + - pygments ; extra == 'rtd' + - pydot ; extra == 'rtd' + - jax ; extra == 'jax' + - jaxlib ; extra == 'jax' + - numba>=0.58,<=0.66.0 ; extra == 'numba' + - llvmlite ; extra == 'numba' + - etuples ; extra == 'kanren' + - logical-unification ; extra == 'kanren' + - minikanren ; extra == 'kanren' + - cons ; extra == 'kanren' + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/1b/6d/3fba214c1e5e0f69991677ec3bc17023f0421776975e1de0c682dca475e2/safetensors-0.8.0-cp310-abi3-win_amd64.whl + name: safetensors + version: 0.8.0 + sha256: 096ec1a98435df7beb08853bb5aa9081a84f23d0adc67ed1a0a10550f608373f + requires_dist: + - safetensors[torch] ; extra == 'all' + - safetensors[numpy] ; extra == 'all' + - safetensors[jax] ; extra == 'all' + - safetensors[paddlepaddle] ; extra == 'all' + - safetensors[convert] ; extra == 'all' + - safetensors[quality] ; extra == 'all' + - safetensors[testing] ; extra == 'all' + - safetensors[torch] ; extra == 'convert' + - huggingface-hub>=1.4 ; extra == 'convert' + - safetensors[all] ; extra == 'dev' + - safetensors[pinned-tf] ; extra == 'dev' + - safetensors[numpy] ; extra == 'jax' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' + - numpy>=1.24.6 ; extra == 'numpy' + - safetensors[numpy] ; extra == 'paddlepaddle' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - safetensors[numpy] ; extra == 'pinned-tf' + - tensorflow==2.18.0 ; extra == 'pinned-tf' + - ruff ; extra == 'quality' + - safetensors[numpy] ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' + - safetensors[numpy] ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - setuptools-rust>=1.12.0 ; extra == 'testing' + - pytest>=9.0 ; extra == 'testing' + - pytest-benchmark>=5.2 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' + - fsspec>=2024.6.0 ; extra == 'testing' + - s3fs>=2024.6.0 ; extra == 'testing' + - safetensors[numpy] ; extra == 'tf-nightly' + - tf-nightly ; extra == 'tf-nightly' + - safetensors[numpy] ; extra == 'torch' + - torch>=2.4 ; extra == 'torch' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/28/50/f203ff3a3ddfe19308efc83c5a3a29ed02bf786732ec35e68bf9162f3365/safetensors-0.8.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: safetensors + version: 0.8.0 + sha256: fd6f3f93c9a0a7cc2788ee63fb763353d4bd2e89b0751bc78fcf7dda00bea774 + requires_dist: + - safetensors[torch] ; extra == 'all' + - safetensors[numpy] ; extra == 'all' + - safetensors[jax] ; extra == 'all' + - safetensors[paddlepaddle] ; extra == 'all' + - safetensors[convert] ; extra == 'all' + - safetensors[quality] ; extra == 'all' + - safetensors[testing] ; extra == 'all' + - safetensors[torch] ; extra == 'convert' + - huggingface-hub>=1.4 ; extra == 'convert' + - safetensors[all] ; extra == 'dev' + - safetensors[pinned-tf] ; extra == 'dev' + - safetensors[numpy] ; extra == 'jax' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' + - numpy>=1.24.6 ; extra == 'numpy' + - safetensors[numpy] ; extra == 'paddlepaddle' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - safetensors[numpy] ; extra == 'pinned-tf' + - tensorflow==2.18.0 ; extra == 'pinned-tf' + - ruff ; extra == 'quality' + - safetensors[numpy] ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' + - safetensors[numpy] ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - setuptools-rust>=1.12.0 ; extra == 'testing' + - pytest>=9.0 ; extra == 'testing' + - pytest-benchmark>=5.2 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' + - fsspec>=2024.6.0 ; extra == 'testing' + - s3fs>=2024.6.0 ; extra == 'testing' + - safetensors[numpy] ; extra == 'tf-nightly' + - tf-nightly ; extra == 'tf-nightly' + - safetensors[numpy] ; extra == 'torch' + - torch>=2.4 ; extra == 'torch' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/2a/49/59ea385dc3a62ff498ddf3cfff7c2b41b0f9f9d3c4122b3f1dcb6d6327fe/scipy-1.18.1-cp314-cp314-macosx_12_0_arm64.whl + name: scipy + version: 1.18.1 + sha256: 9554bcc6d715ee87a633a3cc8e7703c6628b100dd29cb8a2efc4c0533c7ff729 + requires_dist: + - numpy>=2.0.0,<2.8 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - scipy-doctest>=2.0.0 ; extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.19.1 ; extra == 'dev' + - pyrefly==0.63.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/4d/da/007be278565871eadd1ce7abda66532cecda68b63363be44f321f3600c43/pytensor-3.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: pytensor + version: 3.3.0 + sha256: 76879ea107d2e0a2c775cf2b5f7edb63e8118017b04d62468a6cb2219b0805ca + requires_dist: + - setuptools>=59.0.0 + - scipy>=1,<2 + - numpy>=2.0 + - numba>=0.58,<=0.66.0 + - filelock>=3.15 + - pytensor[jax] ; extra == 'complete' + - pytensor[numba] ; extra == 'complete' + - pytensor[complete] ; extra == 'development' + - pytensor[tests] ; extra == 'development' + - pytensor[rtd] ; extra == 'development' + - pytest ; extra == 'tests' + - pre-commit ; extra == 'tests' + - pytest-cov>=2.6.1 ; extra == 'tests' + - coverage>=5.1 ; extra == 'tests' + - pytest-benchmark ; extra == 'tests' + - pytest-mock ; extra == 'tests' + - pytest-sphinx ; extra == 'tests' + - pytensor[kanren] ; extra == 'tests' + - sphinx>=5.1.0,<6 ; extra == 'rtd' + - pygments ; extra == 'rtd' + - pydot ; extra == 'rtd' + - jax ; extra == 'jax' + - jaxlib ; extra == 'jax' + - numba>=0.58,<=0.66.0 ; extra == 'numba' + - llvmlite ; extra == 'numba' + - etuples ; extra == 'kanren' + - logical-unification ; extra == 'kanren' + - minikanren ; extra == 'kanren' + - cons ; extra == 'kanren' + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/52/94/d73da0d28f16c45bb9b0a5691b91610b0275c5ef0eb5e43c87cf2dc1bf31/scipy-1.18.1-cp314-cp314-win_amd64.whl + name: scipy + version: 1.18.1 + sha256: 78a0d7c918e74a232394117160e7e3db503377572a45bcef8826e4ab8a35feba + requires_dist: + - numpy>=2.0.0,<2.8 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - scipy-doctest>=2.0.0 ; extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.19.1 ; extra == 'dev' + - pyrefly==0.63.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/66/c5/b46ad28ac3681d035ea21365c5e052149062e1a0a9affd0563d2760ea6ff/numba-0.66.0-cp314-cp314-win_amd64.whl + name: numba + version: 0.66.0 + sha256: bd57790acd20f6a468e0ad333ef6b82355e309a92310fb7dff80e919f01a21a9 + requires_dist: + - llvmlite>=0.48.0.dev0,<0.49 + - numpy>=1.22,<2.5 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6b/89/2a844506d49651e9aa1af6ef95b6bd8031cb1d5a4375edec6155037e04cf/scipy-1.18.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: scipy + version: 1.18.1 + sha256: ac0333bdf38309aa3dcbe7e3fa7ea29e7a2c37c6ea306a757b700ded8e4596ad + requires_dist: + - numpy>=2.0.0,<2.8 + - pytest>=8.0.0 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict>=2.3.1 ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - scipy-doctest>=2.0.0 ; extra == 'test' + - sphinx>=5.0.0,<8.2.0 ; extra == 'doc' + - intersphinx-registry ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-copybutton ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb>=1.2.0 ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.19.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - linkify-it-py ; extra == 'doc' + - tabulate ; extra == 'doc' + - click<8.3.0 ; extra == 'dev' + - spin ; extra == 'dev' + - mypy==1.19.1 ; extra == 'dev' + - pyrefly==0.63.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.12.0 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + requires_python: '>=3.12' +- pypi: https://files.pythonhosted.org/packages/8d/8e/8170f2e0c217f88069c333d85bb976e536b332aecfcce606ddbdb249385f/llvmlite-0.48.0-cp314-cp314-macosx_12_0_arm64.whl + name: llvmlite + version: 0.48.0 + sha256: 321f1ac39b462603f0b589751aecf2d237d056f6d005749c1752b6f23ec3f074 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl + name: numpy + version: 2.4.6 + sha256: 38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7 + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/95/9c/c510029fc6ef33a6275cd2c5d3cecd6613dfd6aa401d57c54f1c18852ccf/setuptools-84.0.0-py3-none-any.whl + name: setuptools + version: 84.0.0 + sha256: 51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670 + requires_dist: + - pytest>=6,!=8.1.* ; extra == 'test' + - virtualenv>=13.0.0 ; extra == 'test' + - wheel>=0.44.0 ; extra == 'test' + - pip>=19.1 ; extra == 'test' + - packaging>=24.2 ; extra == 'test' + - jaraco-envs>=2.2 ; extra == 'test' + - pytest-xdist>=3 ; extra == 'test' + - jaraco-path>=3.7.2 ; extra == 'test' + - build[virtualenv]>=1.0.3 ; extra == 'test' + - filelock>=3.4.0 ; extra == 'test' + - ini2toml[lite]>=0.14 ; extra == 'test' + - tomli-w>=1.0.0 ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-perf ; sys_platform != 'cygwin' and extra == 'test' + - jaraco-develop>=7.21 ; python_full_version >= '3.9' and sys_platform != 'cygwin' and extra == 'test' + - pytest-home>=0.5 ; extra == 'test' + - pytest-subprocess ; extra == 'test' + - pyproject-hooks!=1.1 ; extra == 'test' + - jaraco-test>=5.5 ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pygments-github-lexers==0.0.5 ; extra == 'doc' + - sphinx-favicon ; extra == 'doc' + - sphinx-inline-tabs ; extra == 'doc' + - sphinx-reredirects ; extra == 'doc' + - sphinxcontrib-towncrier ; extra == 'doc' + - sphinx-notfound-page>=1,<2 ; extra == 'doc' + - pyproject-hooks!=1.1 ; extra == 'doc' + - towncrier<24.7 ; extra == 'doc' + - packaging>=24.2 ; extra == 'core' + - more-itertools>=8.8 ; extra == 'core' + - jaraco-text>=3.7 ; extra == 'core' + - importlib-metadata>=6 ; python_full_version < '3.10' and extra == 'core' + - tomli>=2.0.1 ; python_full_version < '3.11' and extra == 'core' + - wheel>=0.43.0 ; extra == 'core' + - jaraco-functools>=4 ; extra == 'core' + - more-itertools ; extra == 'core' + - pytest-checkdocs>=2.14 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - ruff>=0.13.0 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=3.4 ; extra == 'enabler' + - pytest-mypy>=1.0.1 ; platform_python_implementation != 'PyPy' and extra == 'type' + - mypy==1.18.* ; extra == 'type' + - importlib-metadata>=7.0.2 ; python_full_version < '3.10' and extra == 'type' + - jaraco-develop>=7.21 ; sys_platform != 'cygwin' and extra == 'type' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/96/7a/7e0e73550eb4e41ede6e72fb5371f4539537a4d770a3b73fa9b61aea0622/numba-0.66.0-cp314-cp314-macosx_12_0_arm64.whl + name: numba + version: 0.66.0 + sha256: 46ae5f2b19e2af3c33c2df100306a90ea2f981c8158b0390f8bf6c20eee7357e + requires_dist: + - llvmlite>=0.48.0.dev0,<0.49 + - numpy>=1.22,<2.5 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9e/74/3b17e08f1d9facfa7772ed32e1614f2e676f44093b2b717dae89a0c44161/pytensor-3.3.0-cp314-cp314-macosx_11_0_arm64.whl + name: pytensor + version: 3.3.0 + sha256: 5728796ba3bbefb196311495315ebcd7db39f19564674ab958d5e92e02df5ead + requires_dist: + - setuptools>=59.0.0 + - scipy>=1,<2 + - numpy>=2.0 + - numba>=0.58,<=0.66.0 + - filelock>=3.15 + - pytensor[jax] ; extra == 'complete' + - pytensor[numba] ; extra == 'complete' + - pytensor[complete] ; extra == 'development' + - pytensor[tests] ; extra == 'development' + - pytensor[rtd] ; extra == 'development' + - pytest ; extra == 'tests' + - pre-commit ; extra == 'tests' + - pytest-cov>=2.6.1 ; extra == 'tests' + - coverage>=5.1 ; extra == 'tests' + - pytest-benchmark ; extra == 'tests' + - pytest-mock ; extra == 'tests' + - pytest-sphinx ; extra == 'tests' + - pytensor[kanren] ; extra == 'tests' + - sphinx>=5.1.0,<6 ; extra == 'rtd' + - pygments ; extra == 'rtd' + - pydot ; extra == 'rtd' + - jax ; extra == 'jax' + - jaxlib ; extra == 'jax' + - numba>=0.58,<=0.66.0 ; extra == 'numba' + - llvmlite ; extra == 'numba' + - etuples ; extra == 'kanren' + - logical-unification ; extra == 'kanren' + - minikanren ; extra == 'kanren' + - cons ; extra == 'kanren' + requires_python: '>=3.12,<3.15' +- pypi: https://files.pythonhosted.org/packages/c9/2d/6a5171fb7236ac0895e1a02ccba3735bf291e8597239aa6421894d3c0ba8/llvmlite-0.48.0-cp314-cp314-win_amd64.whl + name: llvmlite + version: 0.48.0 + sha256: 966dcab0a598e2bd8fb5f2cc082cf7b07bae564fc485a3a8692393caf986facf + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d6/e1/05b50692b647cac3c18200ac485b04f342f00ed173c9cc46767274469a15/llvmlite-0.48.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: llvmlite + version: 0.48.0 + sha256: 05f0103c8f2f96a37441337e3643863c01b8e83e530aff38960dcb383c54a065 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl + name: numpy + version: 2.4.6 + sha256: b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261 + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: numpy + version: 2.4.6 + sha256: a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8 + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/f5/b1/fa7c600e7dceae12e9606c7578cbc9ff1e1ed55844883ee5c92205e86226/safetensors-0.8.0-cp310-abi3-macosx_11_0_arm64.whl + name: safetensors + version: 0.8.0 + sha256: c80201d22cbf405b80647a60ada77bba06c8fba2da2743ba1e89cdcc39a81f25 + requires_dist: + - safetensors[torch] ; extra == 'all' + - safetensors[numpy] ; extra == 'all' + - safetensors[jax] ; extra == 'all' + - safetensors[paddlepaddle] ; extra == 'all' + - safetensors[convert] ; extra == 'all' + - safetensors[quality] ; extra == 'all' + - safetensors[testing] ; extra == 'all' + - safetensors[torch] ; extra == 'convert' + - huggingface-hub>=1.4 ; extra == 'convert' + - safetensors[all] ; extra == 'dev' + - safetensors[pinned-tf] ; extra == 'dev' + - safetensors[numpy] ; extra == 'jax' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' + - numpy>=1.24.6 ; extra == 'numpy' + - safetensors[numpy] ; extra == 'paddlepaddle' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - safetensors[numpy] ; extra == 'pinned-tf' + - tensorflow==2.18.0 ; extra == 'pinned-tf' + - ruff ; extra == 'quality' + - safetensors[numpy] ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' + - safetensors[numpy] ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - setuptools-rust>=1.12.0 ; extra == 'testing' + - pytest>=9.0 ; extra == 'testing' + - pytest-benchmark>=5.2 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' + - fsspec>=2024.6.0 ; extra == 'testing' + - s3fs>=2024.6.0 ; extra == 'testing' + - safetensors[numpy] ; extra == 'tf-nightly' + - tf-nightly ; extra == 'tf-nightly' + - safetensors[numpy] ; extra == 'torch' + - torch>=2.4 ; extra == 'torch' + requires_python: '>=3.10' diff --git a/pyproject.toml b/pyproject.toml index dd4977c..6b6eb92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ dependencies = [ [project.urls] Homepage = "https://github.com/pymc-devs/pytensor-ml" +Documentation = "https://pytensor-ml.readthedocs.io" Source = "https://github.com/pymc-devs/pytensor-ml" Tracker = "https://github.com/pymc-devs/pytensor-ml/issues" @@ -145,3 +146,51 @@ warn_unused_ignores = true warn_return_any = false warn_unreachable = true files = ["pytensor_ml"] + +[tool.pixi.workspace] +channels = ["conda-forge"] +platforms = ["osx-arm64", "linux-64", "win-64"] + +# Autodoc imports pytensor_ml, so the docs environment needs the runtime stack alongside sphinx. +# Read the Docs cannot read a pixi environment, so it builds from conda_envs/environment-docs.yml; +# the two lists have to move together. +[tool.pixi.feature.docs.dependencies] +python = ">=3.12" +pytensor = ">=3.3.0,<3.4.0" +numpy = "*" +safetensors = "*" +# The gallery extension renders notebook thumbnails with matplotlib. +matplotlib = "*" +ipython = "*" +jupyter = "*" +sphinx = ">=7" +pydata-sphinx-theme = "*" +myst-nb = "*" +numpydoc = "*" +sphinx-copybutton = "*" +sphinx-design = "*" +sphinx-codeautolink = "*" +sphinx-sitemap = "*" +sphinx-notfound-page = "*" +sphinx-autobuild = "*" +jupyter-sphinx = "*" +sphinxcontrib-bibtex = "*" + +[tool.pixi.feature.docs.pypi-dependencies] +pytensor_ml = { path = ".", editable = true } + +[tool.pixi.feature.docs.tasks] +docs-build = { cmd = "sphinx-build -b html source build/html", cwd = "docs" } +# Rebuilds on save and serves the result at http://localhost:8000. The ignored paths are the ones a +# build writes back into source/ -- the gallery pages and staged notebooks, their thumbnails, and the +# autosummary stubs -- which would otherwise retrigger the watcher and rebuild forever. They are the +# same set docs/.gitignore lists, and have to move together. +docs-serve = { cmd = """\ + sphinx-autobuild source build/html --port 8000 --open-browser \ + --ignore '*/source/examples/*' \ + --ignore '*/source/_thumbnails/*' \ + --ignore '*/source/api/generated/*'\ +""", cwd = "docs" } + +[tool.pixi.environments] +docs = { features = ["docs"] } diff --git a/pytensor_ml/activations.py b/pytensor_ml/activations.py index f1cf253..a91f9d6 100644 --- a/pytensor_ml/activations.py +++ b/pytensor_ml/activations.py @@ -20,7 +20,29 @@ def _constant_like(value: float, x: pt.TensorVariable) -> pt.TensorVariable: return pt.constant(np.asarray(value, dtype=dtype)) -class Activation(Layer): ... +class Activation(Layer): + """ + Base class for the elementwise nonlinearities, each of which is called on an activation. + + Examples + -------- + Subclass it to add a nonlinearity of your own; the body builds a graph from its input: + + .. code-block:: python + + import pytensor.tensor as pt + + from pytensor_ml.activations import Activation + from pytensor_ml.layers import Input + + + class HardTanh(Activation): + def __call__(self, X): + return pt.clip(X, -1.0, 1.0) + + + activations = HardTanh()(Input("X", shape=(None, 4))) + """ class ReLU(Activation): @@ -32,6 +54,22 @@ class ReLU(Activation): .. math:: \mathrm{ReLU}(x) = \max(0, x). + + Examples + -------- + Drop it into a stack wherever a nonlinearity belongs, usually straight after a linear layer: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc", n_in=4, n_out=8), + ReLU(), + ) + activations = network(X) """ def __call__(self, x: pt.TensorLike) -> pt.TensorVariable: @@ -55,6 +93,23 @@ class LeakyReLU(Activation): ---------- negative_slope : float, optional The slope :math:`\alpha` applied to negative inputs. Default is 0.01. + + Examples + -------- + The slope below zero is what separates it from :class:`ReLU`, and a wider one keeps more gradient + flowing through units that would otherwise be dead: + + .. code-block:: python + + from pytensor_ml.activations import LeakyReLU + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc", n_in=4, n_out=8), + LeakyReLU(negative_slope=0.2), + ) + activations = network(X) """ def __init__(self, negative_slope: float = 0.01): @@ -76,6 +131,22 @@ class Tanh(Activation): .. math:: \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}. + + Examples + -------- + Squash an activation into ``(-1, 1)``, keeping it centred on zero: + + .. code-block:: python + + from pytensor_ml.activations import Tanh + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc", n_in=4, n_out=8), + Tanh(), + ) + activations = network(X) """ def __call__(self, x: pt.TensorLike) -> pt.TensorVariable: @@ -93,6 +164,22 @@ class Sigmoid(Activation): .. math:: \sigma(x) = \frac{1}{1 + e^{-x}}. + + Examples + -------- + Squash an activation into ``(0, 1)``, which is what a binary output head wants: + + .. code-block:: python + + from pytensor_ml.activations import Sigmoid + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc", n_in=4, n_out=8), + Sigmoid(), + ) + activations = network(X) """ def __call__(self, x: pt.TensorLike) -> pt.TensorVariable: @@ -110,6 +197,22 @@ class SoftPlus(Activation): .. math:: \mathrm{softplus}(x) = \log(1 + e^x). + + Examples + -------- + Reach for it where an output has to stay strictly positive, such as a predicted scale: + + .. code-block:: python + + from pytensor_ml.activations import SoftPlus + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc", n_in=4, n_out=8), + SoftPlus(), + ) + activations = network(X) """ def __call__(self, x: pt.TensorLike) -> pt.TensorVariable: @@ -142,6 +245,23 @@ class GELU(Activation): This is the variant HuggingFace calls ``"gelu_new"`` / ``"gelu_pytorch_tanh"``, PyTorch exposes as ``nn.GELU(approximate="tanh")``, and Flax as ``gelu(approximate=True)``; GPT-2 uses it. It is cheaper to evaluate than the exact :math:`\operatorname{erf}` form. Default is True. + + Examples + -------- + The default takes the tanh approximation. Pass ``approximate=False`` for the exact error-function + form, which costs more to evaluate: + + .. code-block:: python + + from pytensor_ml.activations import GELU + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc", n_in=4, n_out=8), + GELU(approximate=False), + ) + activations = network(X) """ def __init__(self, approximate: bool = True): @@ -175,6 +295,22 @@ class Swish(Activation): beta : float, optional Slope of the sigmoid gate. Larger :math:`\beta` sharpens the gate toward a ReLU; :math:`\beta \to 0` collapses it toward the linear map :math:`x/2`. Default is 1.0. + + Examples + -------- + Raise ``beta`` to sharpen the gate towards ReLU's hinge, or lower it to soften towards a linear unit: + + .. code-block:: python + + from pytensor_ml.activations import Swish + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc", n_in=4, n_out=8), + Swish(beta=1.5), + ) + activations = network(X) """ def __init__(self, beta: float = 1.0): @@ -201,6 +337,24 @@ class Softmax(Activation): ---------- axis : int, optional The axis along which the values sum to one. Default is -1. + + Examples + -------- + Normalizes over the last axis by default, which is the class axis of a ``(batch, classes)`` logit + matrix. A loss built with ``expect_logits=True`` wants the logits themselves, so reach for this only + when you need the probabilities: + + .. code-block:: python + + from pytensor_ml.activations import Softmax + from pytensor_ml.layers import Input, Linear, Sequential + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("logits", n_in=4, n_out=3), + Softmax(axis=-1), + ) + probabilities = network(X) """ def __init__(self, axis: int = -1): diff --git a/pytensor_ml/base.py b/pytensor_ml/base.py index 03bff42..abf3ba8 100644 --- a/pytensor_ml/base.py +++ b/pytensor_ml/base.py @@ -17,8 +17,35 @@ def _check_input_rank(X: TensorVariable, name: str, n_spatial: int) -> None: class Layer(ABC): - """Base class for the objects that build layer graphs. Defined here, not in ``pytensor_ml.layers``, so - that ``pytensor_ml.activations`` can subclass it without a circular import.""" + """ + Base class for the objects that build layer graphs. Defined here, not in ``pytensor_ml.layers``, so + that ``pytensor_ml.activations`` can subclass it without a circular import. + + Examples + -------- + Subclass it when a layer owns parameters or needs a marker op of its own; for anything stateless a + plain function is enough. The constructor builds the parameters once, and ``__call__`` builds the graph: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.base import Layer + from pytensor_ml.layers import Input + from pytensor_ml.params import trainable + from pytensor_ml.state import ZeroInitializer + + + class Bias(Layer): + def __init__(self, name, n_in): + self.b = trainable(np.zeros(n_in), f"{name}_b", initializer=ZeroInitializer()) + + def __call__(self, X): + return X + self.b + + + activations = Bias("bias", n_in=4)(Input("X", shape=(None, 4))) + """ @abstractmethod def __call__(self, x: pt.TensorLike) -> pt.TensorVariable: ... diff --git a/pytensor_ml/checkpoint.py b/pytensor_ml/checkpoint.py index a89d23b..9af73e6 100644 --- a/pytensor_ml/checkpoint.py +++ b/pytensor_ml/checkpoint.py @@ -40,6 +40,25 @@ def save_state(shared_variables: Sequence[SharedVariable], path: str | Path) -> Variables whose values to save. Every variable must have a unique, non-``None`` name. path : str or pathlib.Path Destination archive, written verbatim. + + Examples + -------- + Write parameter values to safetensors, keyed by name. This is the checkpoint half of a run: it + saves what the parameters hold, not what built them. The destination directory has to exist + already: + + .. code-block:: python + + from pytensor_ml import save_state + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.pytensorf import collect_shared_variables + + X = Input("X", shape=(None, 64)) + logits = Linear("logits", n_in=64, n_out=10)(X) + Model(X, logits).initialize(seed=0) + + save_state(collect_shared_variables(logits), "weights.safetensors") """ indexed = _index_by_name(shared_variables) tensors = { @@ -87,6 +106,26 @@ def load_state( Maps a variable's name to the archive key to read it from, for loading a checkpoint saved under different names (such as HuggingFace's). The mapping must be injective. Names absent from the map are matched directly. + + Examples + -------- + Fill an existing graph's parameters from a checkpoint, matching them by name. Build the same network + first -- this loads values into it rather than reconstructing it: + + .. code-block:: python + + from pytensor_ml import load_state, save_state + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.pytensorf import collect_shared_variables + + X = Input("X", shape=(None, 64)) + logits = Linear("logits", n_in=64, n_out=10)(X) + Model(X, logits).initialize(seed=0) + + shared = collect_shared_variables(logits) + save_state(shared, "weights.safetensors") + load_state(shared, "weights.safetensors") """ indexed = _index_by_name(shared_variables) name_map = name_map or {} diff --git a/pytensor_ml/json_serialize.py b/pytensor_ml/json_serialize.py index ecdaedb..ed5090a 100644 --- a/pytensor_ml/json_serialize.py +++ b/pytensor_ml/json_serialize.py @@ -40,7 +40,7 @@ def serialize_graph(inputs: Sequence[Variable], outputs: Sequence[Variable]) -> Returns ------- - dict + serialized_graph : dict A JSON-native description of the graph's structure (no parameter values). """ return graph_to_json(list(inputs), list(outputs)) diff --git a/pytensor_ml/layers/attention.py b/pytensor_ml/layers/attention.py index b4516ec..ad8dc69 100644 --- a/pytensor_ml/layers/attention.py +++ b/pytensor_ml/layers/attention.py @@ -110,8 +110,26 @@ def scaled_dot_product_attention( Returns ------- - TensorVariable + output : TensorVariable Attention output, shape ``(..., n_head, q_len, v_dim)``. + + Examples + -------- + The bare attention kernel, for building an attention variant of your own. It takes heads as an explicit + axis -- ``(batch, n_head, time, head_dim)`` -- and knows nothing about positions, so rotary or other + positional schemes are applied to ``q`` and ``k`` before the call: + + .. code-block:: python + + import pytensor.tensor as pt + + from pytensor_ml.layers import scaled_dot_product_attention + + q = pt.tensor("q", shape=(None, 8, 128, 32)) + k = pt.tensor("k", shape=(None, 8, 128, 32)) + v = pt.tensor("v", shape=(None, 8, 128, 32)) + + attended = scaled_dot_product_attention(q, k, v, is_causal=True) """ q, k, v = (pt.as_tensor(t).copy() for t in (q, k, v)) inputs = [q, k, v] @@ -157,6 +175,19 @@ class MultiheadAttention(Layer): How the output projection's weight is drawn. The three input projections are unaffected, which is what a scaling applied only to the projection writing back into a residual stream needs. Xavier normal when omitted, as for any other weight. + + Examples + -------- + Attend over a sequence with several heads at once, taking ``(batch, time, n_embd)``. Set + ``n_kv_head`` below ``n_head`` for grouped-query attention, which shrinks the key/value cache that + dominates memory at inference: + + .. code-block:: python + + from pytensor_ml.layers import Input, MultiheadAttention + + X = Input("X", shape=(None, 128, 256)) + attended = MultiheadAttention("attn", n_embd=256, n_head=8, n_kv_head=2)(X) """ def __init__( @@ -240,6 +271,18 @@ class CausalSelfAttention(MultiheadAttention): Include bias terms in the projections. Default is True. out_proj_initializer : Initializer, optional How the output projection's weight is drawn. See :class:`MultiheadAttention`. + + Examples + -------- + :class:`MultiheadAttention` with the causal mask always on, so no position sees a later one. This is + the decoder-side layer a language model stacks: + + .. code-block:: python + + from pytensor_ml.layers import CausalSelfAttention, Input + + X = Input("X", shape=(None, 128, 256)) + attended = CausalSelfAttention("attn", n_embd=256, n_head=8)(X) """ def __init__( diff --git a/pytensor_ml/layers/combinators.py b/pytensor_ml/layers/combinators.py index 655a4ce..009660b 100644 --- a/pytensor_ml/layers/combinators.py +++ b/pytensor_ml/layers/combinators.py @@ -1,4 +1,4 @@ -from collections.abc import Callable +from collections.abc import Callable, Sequence import pytensor.tensor as pt @@ -15,12 +15,48 @@ def Input(name: str, shape: tuple[int | None, ...], dtype: str | None = None) -> Size of each dimension. Use None wherever the size varies between calls, such as a batch axis. dtype : str, optional Data type of the input. Default ``floatX``. + + Examples + -------- + Start every network with one: it names the placeholder a batch is fed to, with ``None`` wherever the + size varies from call to call: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + + X = Input("X", shape=(None, 64)) + activations = Linear("fc", n_in=64, n_out=10)(X) """ return pt.tensor(name=name, shape=shape, dtype=dtype) def Sequential(*layers: Callable) -> Callable: - """Compose layers left to right into a single callable that threads its input through each in turn.""" + """ + Compose layers left to right into a single callable that threads its input through each in turn. + + Examples + -------- + Thread an input through several layers in order. The result is itself callable, so it nests inside + another ``Sequential`` wherever a block repeats: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Input, Linear, Sequential + + block = Sequential( + Linear("fc1", n_in=64, n_out=32), + BatchNorm("bn1", n_in=32), + ReLU(), + ) + network = Sequential( + block, + Linear("logits", n_in=32, n_out=10), + ) + + logits = network(Input("X", shape=(None, 64))) + """ def forward(x: pt.TensorLike) -> pt.TensorLike: for layer in layers: @@ -41,11 +77,95 @@ def Flatten(X: pt.TensorLike) -> pt.TensorVariable: Returns ------- - TensorVariable + flattened : TensorVariable Shape ``(batch, features)``, with ``features`` the product of every remaining axis. + + Examples + -------- + Collapse everything after the batch axis, which is how a convolutional stack hands off to a dense head: + + .. code-block:: python + + from pytensor_ml.layers import Conv2D, Flatten, Input, Linear, MaxPool2D, Sequential + + X = Input("X", shape=(None, 28, 28, 1)) + network = Sequential( + Conv2D("conv", in_channels=1, out_channels=8, kernel_size=3), + MaxPool2D(), + ) + features = network(X) + + logits = Linear("logits", n_in=8 * 13 * 13, n_out=10)(Flatten(features)) """ return pt.join_dims(X, start_axis=1) -Squeeze = pt.squeeze -Concatenate = pt.concatenate +def Squeeze(X: pt.TensorLike, axis: int | Sequence[int] | None = None) -> pt.TensorVariable: + """ + Drop length-1 axes, so a layer that emits a singleton axis feeds one that does not expect it. + + Parameters + ---------- + X : TensorLike + Tensor to squeeze. + axis : int or sequence of int, optional + Axes to drop. An axis whose length is statically known to be anything but 1 is rejected as the + graph is built; an axis of unknown length is accepted and checked when the function runs. + Default None, which drops every axis already known to have length 1 and leaves the rest. + + Returns + ------- + squeezed : TensorVariable + ``X`` with the selected axes removed. + + Examples + -------- + Drop a length-1 axis a layer left behind, such as the trailing feature axis of a single-output + regression head: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear, Squeeze + + X = Input("X", shape=(None, 64)) + prediction = Linear("fc", n_in=64, n_out=1)(X) + + per_row = Squeeze(prediction, axis=-1) + """ + return pt.squeeze(X, axis=axis) + + +def Concatenate(tensors: Sequence[pt.TensorLike], axis: int = 0) -> pt.TensorVariable: + """ + Join tensors end to end along one axis. + + Parameters + ---------- + tensors : sequence of TensorLike + Tensors to join. Every one must agree in rank, and in size on every axis but ``axis``. + axis : int, optional + Axis to join along; negative values count from the right. Default 0, which for a batched + activation is the batch axis -- merging two ``(batch, features)`` branches feature-wise wants + ``axis=-1``. + + Returns + ------- + joined : TensorVariable + The inputs joined, with extent along ``axis`` equal to the sum of the inputs' extents. + + Examples + -------- + Merge parallel branches back into one tensor. Pass ``axis=-1`` to join along features, since the + default of 0 joins along the batch: + + .. code-block:: python + + from pytensor_ml.layers import Concatenate, Input, Linear + + X = Input("X", shape=(None, 64)) + wide = Linear("wide", n_in=64, n_out=8)(X) + deep = Linear("deep", n_in=64, n_out=4)(X) + + merged = Concatenate([wide, deep], axis=-1) + """ + return pt.concatenate(tensors, axis=axis) diff --git a/pytensor_ml/layers/conv.py b/pytensor_ml/layers/conv.py index 03151fd..322a2ea 100644 --- a/pytensor_ml/layers/conv.py +++ b/pytensor_ml/layers/conv.py @@ -304,7 +304,7 @@ def _extract_patches( Returns ------- - TensorVariable + patches : TensorVariable Shape ``(batch, *out_spatial, *kernel_size, channels)``, where ``out_spatial`` counts the windows that fit. """ @@ -772,7 +772,7 @@ def __call__(self, X: pt.TensorLike) -> TensorVariable: Returns ------- - TensorVariable + output : TensorVariable Shape ``(batch, *out_spatial, out_channels)``. """ X = pt.as_tensor(X) @@ -830,6 +830,18 @@ class Conv1D(_ConvNd): How :math:`W` is drawn. Xavier normal when omitted, whose fans count the receptive field. bias_initializer : Initializer, optional How :math:`b` is drawn. Zeros when omitted. + + Examples + -------- + Slide a learned kernel along one spatial axis. The layout is channels-last, so a batch of sequences is + ``(batch, time, channels)``: + + .. code-block:: python + + from pytensor_ml.layers import Conv1D, Input + + X = Input("X", shape=(None, 128, 16)) + features = Conv1D("conv", in_channels=16, out_channels=32, kernel_size=5, padding="same")(X) """ n_spatial = 1 @@ -879,6 +891,25 @@ class Conv2D(_ConvNd): How :math:`W` is drawn. Xavier normal when omitted, whose fans count the receptive field. bias_initializer : Initializer, optional How :math:`b` is drawn. Zeros when omitted. + + Examples + -------- + The image workhorse, taking ``(batch, height, width, channels)``. Padding ``"valid"`` shrinks each + spatial extent by ``kernel_size - 1``; ``"same"`` holds it at ``ceil(extent / stride)``: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import Conv2D, Input, Sequential + + X = Input("X", shape=(None, 32, 32, 3)) + network = Sequential( + Conv2D("conv1", in_channels=3, out_channels=16, kernel_size=3, padding="same"), + ReLU(), + Conv2D("conv2", in_channels=16, out_channels=32, kernel_size=3, stride=2), + ) + + features = network(X) """ n_spatial = 2 @@ -938,7 +969,7 @@ def __call__(self, X: pt.TensorLike) -> TensorVariable: Returns ------- - TensorVariable + output : TensorVariable Shape ``(batch, *out_spatial, out_channels)``, where each output axis is ``(spatial - 1) * stride - 2 * padding + dilation * (kernel_size - 1) + output_padding + 1``. """ @@ -1023,6 +1054,18 @@ class ConvTranspose1D(_ConvTransposeNd): How the kernel is drawn. Xavier normal when omitted. bias_initializer : Initializer, optional How the bias is drawn. Zeros when omitted. + + Examples + -------- + Run a convolution's gradient forwards, so the sequence grows rather than shrinks. A stride of 2 roughly + doubles the extent, which is what a decoder wants: + + .. code-block:: python + + from pytensor_ml.layers import ConvTranspose1D, Input + + X = Input("X", shape=(None, 32, 16)) + upsampled = ConvTranspose1D("up", in_channels=16, out_channels=8, kernel_size=4, stride=2)(X) """ n_spatial = 1 @@ -1064,6 +1107,18 @@ class ConvTranspose2D(_ConvTransposeNd): How the kernel is drawn. Xavier normal when omitted. bias_initializer : Initializer, optional How the bias is drawn. Zeros when omitted. + + Examples + -------- + The upsampling half of an autoencoder or a generator: each input position paints a kernel-sized patch + into the output, so a stride of 2 roughly doubles both extents: + + .. code-block:: python + + from pytensor_ml.layers import ConvTranspose2D, Input + + X = Input("X", shape=(None, 8, 8, 64)) + upsampled = ConvTranspose2D("up", in_channels=64, out_channels=32, kernel_size=4, stride=2)(X) """ n_spatial = 2 @@ -1104,7 +1159,7 @@ def __call__(self, X: pt.TensorLike) -> TensorVariable: Returns ------- - TensorVariable + pooled : TensorVariable Shape ``(batch, *out_spatial, channels)``, with the channel axis untouched. """ X = pt.as_tensor(X) @@ -1118,11 +1173,11 @@ def __call__(self, X: pt.TensorLike) -> TensorVariable: class MaxPool2D(_PoolNd): - """ + r""" Downsample by taking the largest activation in each window, over two spatial axes. Takes ``(batch, height, width, channels)`` and returns ``(batch, out_height, out_width, channels)``. - Padding fills with :math:`-\\infty` so a padded position never wins a window, which zero-filling + Padding fills with :math:`-\infty` so a padded position never wins a window, which zero-filling would do wherever every real activation is negative. Where a window ties, the whole gradient goes to the earliest tap; a backend that pools with its own kernel may instead split the gradient between the tied taps, but every backend returns exactly the gradient the window received. @@ -1139,8 +1194,25 @@ class MaxPool2D(_PoolNd): dilation : int or tuple of int, optional Spacing between the positions a window covers. Default is 1. padding : {"valid", "same"}, int, or tuple of int, optional - No padding, enough to leave each output extent at :math:`\\lceil \text{extent} / s \rceil`, or + No padding, enough to leave each output extent at :math:`\lceil \text{extent} / s \rceil`, or an explicit number of elements on each side. Default is "valid". + + Examples + -------- + Downsample by keeping the largest activation in each window. Stride defaults to ``kernel_size``, so + windows tile without overlapping and a 2x2 pool halves both extents: + + .. code-block:: python + + from pytensor_ml.layers import Conv2D, Input, MaxPool2D, Sequential + + X = Input("X", shape=(None, 32, 32, 3)) + network = Sequential( + Conv2D("conv", in_channels=3, out_channels=16, kernel_size=3, padding="same"), + MaxPool2D(kernel_size=2), + ) + + features = network(X) """ n_spatial = 2 @@ -1148,7 +1220,25 @@ class MaxPool2D(_PoolNd): class MaxPool1D(_PoolNd): - """Downsample a sequence by taking the largest activation in each window; see :class:`MaxPool2D`.""" + """ + Downsample a sequence by taking the largest activation in each window; see :class:`MaxPool2D`. + + Examples + -------- + The one-dimensional pool, keeping the largest activation in each window along the time axis: + + .. code-block:: python + + from pytensor_ml.layers import Conv1D, Input, MaxPool1D, Sequential + + X = Input("X", shape=(None, 128, 16)) + network = Sequential( + Conv1D("conv", in_channels=16, out_channels=32, kernel_size=5, padding="same"), + MaxPool1D(kernel_size=2), + ) + + features = network(X) + """ n_spatial = 1 reduction = "max" @@ -1161,6 +1251,18 @@ class AvgPool2D(_PoolNd): Takes ``(batch, height, width, channels)`` and returns ``(batch, out_height, out_width, channels)``. Padded positions count toward the average as zeros, matching torch's ``count_include_pad``. See :class:`MaxPool2D` for the arguments, which are shared. + + Examples + -------- + Average each window instead of taking its maximum, which keeps every activation in the window rather + than routing the whole gradient to one of them: + + .. code-block:: python + + from pytensor_ml.layers import AvgPool2D, Input + + X = Input("X", shape=(None, 32, 32, 16)) + pooled = AvgPool2D(kernel_size=2)(X) """ n_spatial = 2 @@ -1168,7 +1270,20 @@ class AvgPool2D(_PoolNd): class AvgPool1D(_PoolNd): - """Downsample a sequence by averaging each window; see :class:`AvgPool2D`.""" + """ + Downsample a sequence by averaging each window; see :class:`AvgPool2D`. + + Examples + -------- + The one-dimensional average pool, smoothing along the time axis rather than picking a winner per window: + + .. code-block:: python + + from pytensor_ml.layers import AvgPool1D, Input + + X = Input("X", shape=(None, 128, 16)) + pooled = AvgPool1D(kernel_size=2)(X) + """ n_spatial = 1 reduction = "mean" diff --git a/pytensor_ml/layers/dropout.py b/pytensor_ml/layers/dropout.py index 05701a2..b5ececb 100644 --- a/pytensor_ml/layers/dropout.py +++ b/pytensor_ml/layers/dropout.py @@ -36,6 +36,25 @@ class Dropout(Layer): generators : list of RandomGeneratorSharedVariable One generator per application of the layer, in the order they were applied. Set a value on these to steer or restore the masks. + + Examples + -------- + Zero a random share of activations during training, rescaling the survivors so the mean is unchanged. + :meth:`~pytensor_ml.model.Model.predict` drops the layer entirely, so inference is deterministic: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import Dropout, Input, Linear, Sequential + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + ReLU(), + Dropout(p=0.1, random_state=0), + ) + + activations = network(X) """ def __init__(self, name: str | None = None, p: float = 0.5, random_state: Any | None = None): diff --git a/pytensor_ml/layers/embedding.py b/pytensor_ml/layers/embedding.py index 92f36b9..e4fc034 100644 --- a/pytensor_ml/layers/embedding.py +++ b/pytensor_ml/layers/embedding.py @@ -33,6 +33,18 @@ class Embedding(Layer): the vocabulary size in the denominator -- correct Xavier, and much tighter than the ``NormalInitializer(0.0, 0.02)`` that reference implementations of GPT-2 use, so this is the keyword to reach for when matching one. + + Examples + -------- + Look up a learned vector per integer token, which is how a vocabulary enters a network. The input + carries token ids, so it must be an integer tensor: + + .. code-block:: python + + from pytensor_ml.layers import Embedding, Input + + tokens = Input("tokens", shape=(None, 128), dtype="int64") + embedded = Embedding("embed", n_embeddings=50_000, n_features=256)(tokens) """ def __init__( diff --git a/pytensor_ml/layers/linear.py b/pytensor_ml/layers/linear.py index c78ab2a..0d9b1c2 100644 --- a/pytensor_ml/layers/linear.py +++ b/pytensor_ml/layers/linear.py @@ -45,6 +45,23 @@ class Linear(Layer): Both parameters are drawn when the layer is built, so a network trains without any further call. :meth:`~pytensor_ml.model.Model.initialize` redraws them from a single seed, which is what makes a run reproducible. + + Examples + -------- + The dense layer: multiply by a learned matrix and add a learned bias. Pass ``bias=False`` where a + normalization layer follows and would subtract the bias away again: + + .. code-block:: python + + from pytensor_ml.layers import BatchNorm, Input, Linear, Sequential + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32, bias=False), + BatchNorm("bn", n_in=32), + ) + + activations = network(X) """ def __init__( diff --git a/pytensor_ml/layers/norm.py b/pytensor_ml/layers/norm.py index a7f6b60..abd2c89 100644 --- a/pytensor_ml/layers/norm.py +++ b/pytensor_ml/layers/norm.py @@ -194,6 +194,26 @@ class BatchNorm(Layer): be batched with. Compile prediction graphs with :func:`compile_predict`, which applies :func:`rewrite_for_prediction` to substitute the accumulated running statistics for the batch statistics. + + Examples + -------- + Normalize each feature over the batch, keeping running statistics so inference does not depend on which + other rows happen to share the batch. :meth:`~pytensor_ml.model.Model.predict` swaps in those running + statistics automatically, so the training and inference graphs differ here: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Input, Linear, Sequential + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32, bias=False), + BatchNorm("bn", n_in=32), + ReLU(), + ) + + activations = network(X) """ def __init__( @@ -334,6 +354,23 @@ class LayerNorm(Layer): factor to rescale a normalized activation by would defeat the layer. loc_initializer : Initializer, optional How :math:`\beta` is drawn. Zeros when omitted. + + Examples + -------- + Normalize each row over its own features, so no row depends on the others. That independence is why a + transformer uses it rather than :class:`BatchNorm`, and it needs no running statistics: + + .. code-block:: python + + from pytensor_ml.layers import Input, LayerNorm, Linear, Sequential + + X = Input("X", shape=(None, 128, 256)) + network = Sequential( + LayerNorm("ln", n_in=256), + Linear("fc", n_in=256, n_out=256), + ) + + activations = network(X) """ def __init__( diff --git a/pytensor_ml/layers/padding.py b/pytensor_ml/layers/padding.py index 29c26d0..8deb6d1 100644 --- a/pytensor_ml/layers/padding.py +++ b/pytensor_ml/layers/padding.py @@ -114,7 +114,7 @@ def __call__(self, X: pt.TensorLike) -> TensorVariable: Returns ------- - TensorVariable + padded : TensorVariable Shape ``(batch, *padded_spatial, channels)``, with batch and channels untouched. """ X = pt.as_tensor(X) @@ -153,6 +153,22 @@ class ZeroPad1D(_PadNd): padding : int or pair of int, optional Elements added before and after the time axis, either shared by both ends or given as ``(before, after)``. Default is 0. + + Examples + -------- + Pad a sequence with zeros on both ends, most often to keep a convolution's output length: + + .. code-block:: python + + from pytensor_ml.layers import Conv1D, Input, Sequential, ZeroPad1D + + X = Input("X", shape=(None, 128, 16)) + network = Sequential( + ZeroPad1D(padding=2), + Conv1D("conv", in_channels=16, out_channels=32, kernel_size=5), + ) + + features = network(X) """ n_spatial = 1 @@ -175,6 +191,23 @@ class ZeroPad2D(_PadNd): The same amount on every side, one amount per axis, or an explicit ``(before, after)`` for each. Axes read in input order, so ``((top, bottom), (left, right))`` -- not torch's flat last-axis-first sequence. Default is 0. + + Examples + -------- + Surround an image with zeros so a following convolution keeps its extents. One number pads every + side equally; a pair per axis pads each side separately: + + .. code-block:: python + + from pytensor_ml.layers import Conv2D, Input, Sequential, ZeroPad2D + + X = Input("X", shape=(None, 32, 32, 3)) + network = Sequential( + ZeroPad2D(padding=1), + Conv2D("conv", in_channels=3, out_channels=16, kernel_size=3), + ) + + features = network(X) """ n_spatial = 2 @@ -191,6 +224,22 @@ class ConstantPad1D(_ConstantPadNd): ---------- value : float, optional What the added elements hold. Default is 0.0, which makes this :class:`ZeroPad1D`. + + Examples + -------- + Pad a sequence with a chosen constant, for data where zero is a real value rather than absence: + + .. code-block:: python + + from pytensor_ml.layers import Conv1D, Input, Sequential, ConstantPad1D + + X = Input("X", shape=(None, 128, 16)) + network = Sequential( + ConstantPad1D(padding=2, value=0.5), + Conv1D("conv", in_channels=16, out_channels=32, kernel_size=5), + ) + + features = network(X) """ n_spatial = 1 @@ -206,6 +255,23 @@ class ConstantPad2D(_ConstantPadNd): ---------- value : float, optional What the added elements hold. Default is 0.0, which makes this :class:`ZeroPad2D`. + + Examples + -------- + Pad with a value of your choosing rather than zero, which matters when zero is a meaningful level + in the data rather than a neutral one: + + .. code-block:: python + + from pytensor_ml.layers import Conv2D, Input, Sequential, ConstantPad2D + + X = Input("X", shape=(None, 32, 32, 3)) + network = Sequential( + ConstantPad2D(padding=1, value=0.5), + Conv2D("conv", in_channels=3, out_channels=16, kernel_size=3), + ) + + features = network(X) """ n_spatial = 2 @@ -228,6 +294,23 @@ class ReflectionPad1D(_PadNd): Elements added before and after the time axis. Padding wider than the axis keeps reflecting back and forth rather than failing, which is what numpy does and where torch raises. Default is 0. + + Examples + -------- + Mirror a sequence across its ends, so the padded region continues the signal rather than cutting it + to a constant: + + .. code-block:: python + + from pytensor_ml.layers import Conv1D, Input, Sequential, ReflectionPad1D + + X = Input("X", shape=(None, 128, 16)) + network = Sequential( + ReflectionPad1D(padding=2), + Conv1D("conv", in_channels=16, out_channels=32, kernel_size=5), + ) + + features = network(X) """ n_spatial = 1 @@ -248,6 +331,23 @@ class ReflectionPad2D(_PadNd): padding : int, pair of int, or pair of pair of int, optional Padding wider than the axis it reflects keeps reflecting back and forth rather than failing. Default is 0. + + Examples + -------- + Mirror the image across its edges instead of inventing a constant, which avoids the hard border a + zero pad introduces. The padding must be smaller than the extent it mirrors: + + .. code-block:: python + + from pytensor_ml.layers import Conv2D, Input, Sequential, ReflectionPad2D + + X = Input("X", shape=(None, 32, 32, 3)) + network = Sequential( + ReflectionPad2D(padding=1), + Conv2D("conv", in_channels=3, out_channels=16, kernel_size=3), + ) + + features = network(X) """ n_spatial = 2 @@ -268,6 +368,22 @@ class ReplicationPad1D(_PadNd): Name prefix for the layer's output. Defaults to the class name when None. padding : int or pair of int, optional Elements added before and after the time axis. Default is 0. + + Examples + -------- + Hold the first and last values of a sequence flat across the padded region: + + .. code-block:: python + + from pytensor_ml.layers import Conv1D, Input, Sequential, ReplicationPad1D + + X = Input("X", shape=(None, 128, 16)) + network = Sequential( + ReplicationPad1D(padding=2), + Conv1D("conv", in_channels=16, out_channels=32, kernel_size=5), + ) + + features = network(X) """ n_spatial = 1 @@ -287,6 +403,23 @@ class ReplicationPad2D(_PadNd): Name prefix for the layer's output. Defaults to the class name when None. padding : int, pair of int, or pair of pair of int, optional Default is 0. + + Examples + -------- + Repeat the edge pixel outwards. Like reflection it avoids a hard border, but it holds the boundary + value flat rather than folding the interior back: + + .. code-block:: python + + from pytensor_ml.layers import Conv2D, Input, Sequential, ReplicationPad2D + + X = Input("X", shape=(None, 32, 32, 3)) + network = Sequential( + ReplicationPad2D(padding=1), + Conv2D("conv", in_channels=3, out_channels=16, kernel_size=3), + ) + + features = network(X) """ n_spatial = 2 diff --git a/pytensor_ml/layers/recurrent.py b/pytensor_ml/layers/recurrent.py index dc5955b..7166c5a 100644 --- a/pytensor_ml/layers/recurrent.py +++ b/pytensor_ml/layers/recurrent.py @@ -25,6 +25,42 @@ class RecurrentCell(ABC): A cell owns the parameters its step uses and knows the shape of the state it carries, which is all the loop needs from it. Subclasses implement :meth:`step` and :meth:`initial_state`. + + Examples + -------- + Subclass it to define one timestep and let :class:`Recurrent` scan it over the sequence. A cell owns its + parameters, says how to build its initial state, and maps ``(input, *state)`` to the next state: + + .. code-block:: python + + import numpy as np + import pytensor.tensor as pt + + from pytensor_ml.layers import Input, Recurrent + from pytensor_ml.layers.recurrent import RecurrentCell + from pytensor_ml.params import trainable + from pytensor_ml.state import XavierUniformInitializer + + + class LeakyCell(RecurrentCell): + def __init__(self, name, n_in, n_hidden): + self.n_hidden = n_hidden + self.W = trainable( + np.zeros((n_in + n_hidden, n_hidden)), + f"{name}_W", + initializer=XavierUniformInitializer(), + ) + + def step(self, x_t, h): + candidate = pt.tanh(pt.concatenate([x_t, h], axis=-1) @ self.W) + return (0.5 * h + 0.5 * candidate,) + + def initial_state(self, X): + return (pt.zeros((X.shape[0], self.n_hidden)),) + + + X = Input("X", shape=(None, 50, 16)) + hidden_states = Recurrent(LeakyCell("leaky", n_in=16, n_hidden=32))(X) """ @abstractmethod @@ -41,7 +77,7 @@ def step(self, x_t: TensorVariable, *state: TensorVariable) -> tuple[TensorVaria Returns ------- - tuple of TensorVariable + state : tuple of TensorVariable The new state, in the same order. Its first element is the cell's output, which is what :class:`Recurrent` stacks over time -- an LSTM carrying :math:`(h, c)` returns :math:`h` first. """ @@ -56,7 +92,7 @@ def initial_state(self, X: TensorVariable) -> tuple[TensorVariable, ...]: Returns ------- - tuple of TensorVariable + state : tuple of TensorVariable Zero-filled state, in the order :meth:`step` takes and returns it. """ @@ -80,6 +116,19 @@ class Recurrent(Layer): Run the sequence from its last step to its first. The output stays aligned with the input, so ``out[..., t, :]`` is the step that read ``X[..., t, :]`` either way, and a backward layer's output concatenates elementwise with a forward one's. Default is False. + + Examples + -------- + Wrap any cell to scan it over the time axis. :class:`RNN`, :class:`LSTM` and :class:`GRU` are this + layer around their matching cell, and ``reverse=True`` is what the backward half of a + :class:`Bidirectional` uses: + + .. code-block:: python + + from pytensor_ml.layers import GRUCell, Input, Recurrent + + X = Input("X", shape=(None, 200, 16)) + hidden_states = Recurrent(GRUCell("cell", n_in=16, n_hidden=32), reverse=True)(X) """ def __init__(self, cell: RecurrentCell, name: str | None = None, reverse: bool = False): @@ -115,7 +164,7 @@ def __call__( Returns ------- - TensorVariable + outputs : TensorVariable The cell's output at each step, shape ``(..., time, n_out)``. """ reverse = self.reverse if reverse is None else reverse @@ -251,6 +300,21 @@ class ElmanCell(RecurrentCell): as in keras and flax. bias_initializer : Initializer, optional How :math:`b` is drawn. Zeros when omitted. + + Examples + -------- + One timestep of a plain recurrent layer, for handing to :class:`Recurrent` when you want the scan + configured yourself rather than through :class:`RNN`: + + .. code-block:: python + + from pytensor_ml.activations import Tanh + from pytensor_ml.layers import ElmanCell, Input, Recurrent + + X = Input("X", shape=(None, 50, 16)) + cell = ElmanCell("cell", n_in=16, n_hidden=32, activation=Tanh()) + + hidden_states = Recurrent(cell)(X) """ def __init__( @@ -327,6 +391,18 @@ class RNN(Recurrent): How :math:`b` is drawn. Zeros when omitted. reverse : bool, optional Run the sequence backward, with the output still aligned to the input. Default is False. + + Examples + -------- + The plain recurrent layer: one hidden state carried along the time axis, returning its value at every + step. Input is ``(batch, time, features)``: + + .. code-block:: python + + from pytensor_ml.layers import RNN, Input + + X = Input("X", shape=(None, 50, 16)) + hidden_states = RNN("rnn", n_in=16, n_hidden=32)(X) """ def __init__( @@ -405,6 +481,18 @@ class GRUCell(RecurrentCell): omitted; see :class:`ElmanCell` for why the state's own weight is the sensitive draw. bias_initializer : Initializer, optional How :math:`b` and :math:`c` are drawn. Zeros when omitted. + + Examples + -------- + One timestep of a GRU, carrying a single hidden state. Use it where the scan is built by hand rather + than through :class:`GRU`: + + .. code-block:: python + + from pytensor_ml.layers import GRUCell, Input, Recurrent + + X = Input("X", shape=(None, 200, 16)) + hidden_states = Recurrent(GRUCell("cell", n_in=16, n_hidden=32))(X) """ _n_gates = 3 @@ -504,6 +592,18 @@ class GRU(Recurrent): How the biases are drawn. Zeros when omitted. reverse : bool, optional Run the sequence backward, with the output still aligned to the input. Default is False. + + Examples + -------- + Gated like an :class:`LSTM` but with one state instead of two, so it trains faster and holds fewer + parameters at similar quality on many sequences: + + .. code-block:: python + + from pytensor_ml.layers import GRU, Input + + X = Input("X", shape=(None, 200, 16)) + hidden_states = GRU("gru", n_in=16, n_hidden=32)(X) """ def __init__( @@ -587,6 +687,18 @@ class LSTMCell(RecurrentCell): bias_initializer : Initializer, optional How :math:`b` is drawn. Zeros when omitted, as in torch and flax. Drawing the forget slice at one instead starts the memory holding rather than decaying, which is keras' default. + + Examples + -------- + One timestep of an LSTM, carrying ``(hidden, cell)`` as its state. Reach for it when the scan needs + configuring directly rather than through :class:`LSTM`: + + .. code-block:: python + + from pytensor_ml.layers import Input, LSTMCell, Recurrent + + X = Input("X", shape=(None, 200, 16)) + hidden_states = Recurrent(LSTMCell("cell", n_in=16, n_hidden=32), reverse=True)(X) """ _n_gates = 4 @@ -685,6 +797,18 @@ class LSTM(Recurrent): How :math:`b` is drawn. Zeros when omitted. reverse : bool, optional Run the sequence backward, with the output still aligned to the input. Default is False. + + Examples + -------- + Carries a cell state alongside the hidden state, with gates deciding what to keep. That extra path is + what lets it hold information over far longer sequences than :class:`RNN`: + + .. code-block:: python + + from pytensor_ml.layers import LSTM, Input + + X = Input("X", shape=(None, 200, 16)) + hidden_states = LSTM("lstm", n_in=16, n_hidden=32)(X) """ def __init__( @@ -740,6 +864,21 @@ class Bidirectional(Layer): Run over the sequence from its last step to its first. name : str or None Name for the layer's output. Defaults to "Bidirectional" when None. + + Examples + -------- + Run one layer forwards and another backwards, concatenating their outputs, so every step sees the whole + sequence. Give the two directions separate layers -- sharing one would tie their weights: + + .. code-block:: python + + from pytensor_ml.layers import GRU, Bidirectional, Input + + X = Input("X", shape=(None, 200, 16)) + forward = GRU("forward", n_in=16, n_hidden=32) + backward = GRU("backward", n_in=16, n_hidden=32) + + hidden_states = Bidirectional(forward, backward)(X) """ def __init__(self, forward: Recurrent, backward: Recurrent, name: str | None = None): @@ -766,7 +905,7 @@ def __call__(self, X: pt.TensorLike, *, mask: pt.TensorLike | None = None) -> Te Returns ------- - TensorVariable + outputs : TensorVariable Both directions' outputs, shape ``(..., time, n_forward + n_backward)``. """ out = pt.concatenate( diff --git a/pytensor_ml/layers/transformer.py b/pytensor_ml/layers/transformer.py index 805def8..a7d423b 100644 --- a/pytensor_ml/layers/transformer.py +++ b/pytensor_ml/layers/transformer.py @@ -45,6 +45,19 @@ class FeedForward(Layer): fc_out_initializer : Initializer, optional How the second layer's weight is drawn. The hidden layer is unaffected. Xavier normal when omitted, as for any other weight. + + Examples + -------- + The position-wise MLP of a transformer block: widen by ``mlp_ratio``, apply a nonlinearity, project + back. Pass ``hidden_dim`` to set the width directly instead of as a multiple: + + .. code-block:: python + + from pytensor_ml.activations import GELU + from pytensor_ml.layers import FeedForward, Input + + X = Input("X", shape=(None, 128, 256)) + activations = FeedForward("ff", d_model=256, mlp_ratio=4, activation=GELU())(X) """ def __init__( @@ -128,6 +141,24 @@ class TransformerBlock(Layer): GPT-style initialization asks for: a residual stream accumulates one contribution per block, so those projections are scaled by :math:`1/\sqrt{2 n_\text{layer}}` while the rest are not. The depth is not known here, so the scaling belongs in the initializer the caller passes. + + Examples + -------- + Attention and feed-forward with their residual connections and norms, which is the unit a transformer + repeats. ``norm_first`` puts the norm inside the residual branch, the pre-norm arrangement that trains + stably without a warmup: + + .. code-block:: python + + from pytensor_ml.layers import Input, Sequential, TransformerBlock + + X = Input("X", shape=(None, 128, 256)) + network = Sequential( + TransformerBlock("block1", d_model=256, n_head=8, norm_first=True), + TransformerBlock("block2", d_model=256, n_head=8, norm_first=True), + ) + + activations = network(X) """ def __init__( diff --git a/pytensor_ml/loss.py b/pytensor_ml/loss.py index 8ecf9ad..3365742 100644 --- a/pytensor_ml/loss.py +++ b/pytensor_ml/loss.py @@ -20,6 +20,28 @@ def _as_reduction(reduction: ReductionLike) -> ReductionFunction: class Loss(ABC): + """ + Scalar objective a training step differentiates, called as ``loss(y_true, y_pred)``. + + Examples + -------- + Subclass it by implementing :meth:`loss`; the base class makes the instance callable: + + .. code-block:: python + + import pytensor.tensor as pt + + from pytensor_ml.loss import Loss + + + class MeanAbsoluteError(Loss): + def loss(self, y_true, y_pred): + return pt.abs(y_true - y_pred).mean() + + + objective = MeanAbsoluteError()(pt.vector("y_true"), pt.vector("y_pred")) + """ + @abstractmethod def loss(self, y_true, y_pred) -> pt.TensorVariable: ... @@ -28,6 +50,28 @@ def __call__(self, y_true, y_pred) -> pt.TensorVariable: class SquaredError(Loss): + """ + Mean or summed squared deviation between prediction and target, for regression. + + Examples + -------- + Call the loss on a target and a prediction to get the scalar a training step differentiates: + + .. code-block:: python + + import numpy as np + import pytensor + import pytensor.tensor as pt + + from pytensor_ml.loss import SquaredError + + y_true = pt.matrix("y_true") + y_pred = pt.matrix("y_pred") + + objective = SquaredError()(y_true, y_pred) + value = pytensor.function([y_true, y_pred], objective)(np.ones((4, 1)), np.zeros((4, 1))) + """ + def __init__(self, reduction: ReductionLike = "mean"): self.reduction = _as_reduction(reduction) @@ -38,6 +82,49 @@ def loss(self, y_true, y_pred) -> pt.TensorVariable: class CrossEntropy(Loss): + """ + Negative log likelihood of the true class under the predicted distribution, for classification. + + Examples + -------- + Integer labels against predicted probabilities, the default: + + .. code-block:: python + + import numpy as np + import pytensor + import pytensor.tensor as pt + + from pytensor_ml.loss import CrossEntropy + + labels = pt.vector("labels", dtype="int64") + probabilities = pt.matrix("probabilities") + + objective = CrossEntropy()(labels, probabilities) + value = pytensor.function([labels, probabilities], objective)( + np.array([0, 2]), np.array([[0.7, 0.2, 0.1], [0.1, 0.2, 0.7]]) + ) + + A classifier head emits logits, and one-hot labels are what an encoder produces, so both flags are + usually set together. Passing logits keeps the loss on the numerically stable log-softmax path: + + .. code-block:: python + + import numpy as np + import pytensor + import pytensor.tensor as pt + + from pytensor_ml.loss import CrossEntropy + + onehot = pt.matrix("onehot") + logits = pt.matrix("logits") + + objective = CrossEntropy(expect_logits=True, expect_onehot_labels=True)(onehot, logits) + value = pytensor.function([onehot, logits], objective)( + np.eye(3)[[0, 2]], np.array([[2.0, 0.5, 0.1], [0.1, 0.5, 2.0]]) + ) + """ + def __init__( self, reduction: ReductionLike = "mean", @@ -106,6 +193,24 @@ def supervised_loss( Scalar training loss. target : TensorVariable Input placeholder for the ground-truth labels, to be supplied at call time. + + Examples + -------- + Point it at a model's output and it hands back the target placeholder to feed alongside each batch: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import CrossEntropy, supervised_loss + from pytensor_ml.optim import adam, compile_train + + X = Input("X", shape=(None, 4)) + logits = Linear("logits", n_in=4, n_out=3)(X) + + loss_fn = CrossEntropy(expect_logits=True, expect_onehot_labels=True) + objective, target = supervised_loss(logits, loss_fn, ndim_out=2) + + step = compile_train(objective, adam(1e-3), inputs=[X, target]) """ label_slice = (slice(None),) * ndim_out + (0,) * (prediction.ndim - ndim_out) target = prediction[label_slice].type() diff --git a/pytensor_ml/model.py b/pytensor_ml/model.py index 7e63257..d831998 100644 --- a/pytensor_ml/model.py +++ b/pytensor_ml/model.py @@ -16,7 +16,38 @@ class Model: - """A network's input and output, with conveniences to initialize its weights, train, and run inference.""" + """ + A network's input and output, with conveniences to initialize its weights, train, and run inference. + + Examples + -------- + Build the network, wrap it, and the model carries the graph through initialization, a training + step, and inference: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import Input, Linear, Sequential + from pytensor_ml.loss import SquaredError + from pytensor_ml.model import Model + from pytensor_ml.optim import adam + + X = Input("X", shape=(None, 4)) + network = Sequential( + Linear("fc1", n_in=4, n_out=8), + ReLU(), + Linear("fc2", n_in=8, n_out=1), + ) + + model = Model(X, network(X)).initialize(seed=0) + step = model.compile_train(adam(1e-2), SquaredError(), ndim_out=2) + + batch = np.zeros((16, 4)) + loss_value = step(batch, np.zeros((16, 1))) + predictions = model.predict(batch) + """ def __init__(self, X: TensorVariable, y: TensorVariable, compile_kwargs: dict | None = None): self.X = X diff --git a/pytensor_ml/optim/alias.py b/pytensor_ml/optim/alias.py index 2cf9229..2e168fc 100644 --- a/pytensor_ml/optim/alias.py +++ b/pytensor_ml/optim/alias.py @@ -56,6 +56,25 @@ def sgd( Momentum coefficient. A value of 0 (the default) gives plain SGD. nesterov : bool Use Nesterov momentum. Ignored when ``momentum`` is 0. Default False. + + Examples + -------- + Plain gradient descent by default. Momentum carries a running average of past steps, and + ``nesterov`` measures the gradient after that carry rather than before: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import compile_train, sgd + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, sgd(learning_rate=0.1, momentum=0.9, nesterov=True)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -84,6 +103,25 @@ def adam( ``learning_rate`` accepts a float, a scalar shared variable, any scalar graph, or a schedule; see :func:`sgd`. + + Examples + -------- + The usual first choice: a per-parameter rate adapted from the first and second gradient moments, + both bias-corrected, so the earliest steps are not damped towards zero: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, adam(learning_rate=1e-3)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -120,6 +158,25 @@ def adamw( ``learning_rate`` accepts a float, a scalar shared variable, any scalar graph, or a schedule; see :func:`sgd`. + + Examples + -------- + Adam entangles weight decay with its adaptive rate; this one subtracts the decay from the weights + directly. A ``mask`` keeps biases and norm scales out of it, which is almost always what you want: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adamw, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, adamw(learning_rate=1e-3, mask=lambda parameter: parameter.ndim > 1)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -155,6 +212,25 @@ def nadam( ``learning_rate`` accepts a float, a scalar shared variable, any scalar graph, or a schedule; see :func:`sgd`. + + Examples + -------- + Adam with Nesterov's look-ahead folded into the first moment, which turns corners a little faster + than plain Adam on the same rate: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import compile_train, nadam + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, nadam(learning_rate=2e-3)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -187,6 +263,25 @@ def adamax( ``learning_rate`` accepts a float, a scalar shared variable, any scalar graph, or a schedule; see :func:`sgd`. + + Examples + -------- + Adam's second moment replaced by a running infinity norm, so one outsized gradient cannot shrink + every step for many iterations afterwards: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adamax, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, adamax(learning_rate=2e-3)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -219,6 +314,25 @@ def rprop( Unlike the other rules, ``learning_rate`` must be a plain number: it initializes the per-parameter step sizes Rprop then adapts, so it never enters the graph and cannot be scheduled or steered. + + Examples + -------- + Steps by the sign of the gradient alone, growing or shrinking a per-parameter step size. It reads a + sign change as overshoot, so minibatch noise misleads it -- keep it to full-batch objectives: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import compile_train, rprop + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, rprop(learning_rate=1e-2, eta_plus=1.2, eta_minus=0.5)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ _require_numeric_learning_rate(learning_rate) @@ -249,6 +363,25 @@ def rmsprop( ``learning_rate`` accepts a float, a scalar shared variable, any scalar graph, or a schedule; see :func:`sgd`. + + Examples + -------- + Scales each step by a decaying average of squared gradients. Setting ``centered`` subtracts the + mean gradient first, which estimates variance rather than raw magnitude: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import compile_train, rmsprop + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, rmsprop(learning_rate=1e-2, centered=True)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -276,6 +409,25 @@ def adagrad(learning_rate: LearningRate = 0.01, epsilon: float = 1e-8) -> Update ``learning_rate`` accepts a float, a scalar shared variable, any scalar graph, or a schedule; see :func:`sgd`. + + Examples + -------- + Accumulates every squared gradient it has seen, so the effective rate only ever decreases. That + suits sparse features and stalls on long runs: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adagrad, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, adagrad(learning_rate=1e-2)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -299,6 +451,25 @@ def adadelta( ``learning_rate`` accepts a float, a scalar shared variable, any scalar graph, or a schedule; see :func:`sgd`. + + Examples + -------- + Tracks a window of squared updates alongside squared gradients, so their ratio sets the scale and + the learning rate stays at its default of 1.0: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adadelta, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, adadelta()) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state diff --git a/pytensor_ml/optim/base.py b/pytensor_ml/optim/base.py index 26c43a1..a8b3a9d 100644 --- a/pytensor_ml/optim/base.py +++ b/pytensor_ml/optim/base.py @@ -25,21 +25,140 @@ # carries the next parameter values *and* the next optimizer-state values in one identity-keyed dict. Updates = dict[SharedVariable, TensorVariable] -# A chainable transform reads an updates dict and returns a new one, working in "step space" (updates[p] - p). Transform = Callable[[Updates, Sequence[Parameter]], Updates] +""" +A chainable step transformer, reading an updates dict and returning a new one. + +Transforms work in step space -- ``updates[parameter] - parameter`` -- so one can be written without +knowing which rule produced the step it is adjusting. + +Examples +-------- +Write one as a plain function and :func:`chain` accepts it wherever a built-in transform goes. The +updates dict also carries optimizer state and training clocks, so touch only the entries for +``parameters`` -- rewriting the rest would halve a clock's advance as readily as a step: + +.. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, chain, compile_train + + + def halve_every_step(updates, parameters): + halved = dict(updates) + for parameter in parameters: + halved[parameter] = parameter + 0.5 * (updates[parameter] - parameter) + return halved + + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1e-3), halve_every_step)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) +""" UpdateRule = Callable[[LossOrGradients, Sequence[Parameter]], Updates] +""" +What every optimizer is: a callable taking a loss (or gradients) and the parameters, returning the +updates dict that moves them. + +Examples +-------- +Anything matching the signature is a rule, so a hand-written one composes with the rest of the module: + +.. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import chain, clip_by_global_norm, compile_train, get_gradients + + + def plain_descent(loss_or_gradients, parameters): + gradients = get_gradients(loss_or_gradients, parameters) + return {p: p - 0.01 * gradient for p, gradient in zip(parameters, gradients)} + + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(plain_descent, clip_by_global_norm(1.0))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) +""" -# A learning-rate schedule: symbolic step count in, scalar learning rate out. type Schedule = Callable[[TensorVariable], TensorVariable] +""" +A learning-rate schedule: symbolic step count in, scalar learning rate out. + +Examples +-------- +The built-in schedules return one, and any callable of the same shape works in their place: + +.. code-block:: python + + import pytensor.tensor as pt + + from pytensor_ml.optim import adam + + + def inverse_square_root(step_count): + return 3e-4 / pt.sqrt(pt.maximum(step_count, 1)) + + + rule = adam(learning_rate=inverse_square_root) +""" -# A rate a rule multiplies into its step: a baked-in constant, a shared variable to steer from Python with -# `set_value` or to substitute a schedule into, or any scalar graph, which is what a schedule reading a -# training clock produces. type Rate = float | Parameter | TensorVariable +""" +A rate a rule multiplies into its step. + +Either a baked-in constant, a shared variable to steer from Python with ``set_value`` or to substitute a +schedule into, or any scalar graph, which is what a schedule reading a training clock produces. + +Examples +-------- +A shared scalar is the form to reach for when the rate has to change mid-run without recompiling: + +.. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import compile_train, scalar_state, sgd + + rate = scalar_state("rate", fill_value=0.1) + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, sgd(learning_rate=rate)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) + + rate.set_value(np.array(0.01, dtype=rate.dtype)) +""" -# What an optimizer alias accepts as its rate, adding a schedule that drives it on-graph. type LearningRate = Rate | Schedule +""" +What an optimizer alias accepts as its rate, adding a schedule that drives it on-graph. + +Examples +-------- +Every alias takes either form, so a constant can be swapped for a schedule without touching anything +else: + +.. code-block:: python + + from pytensor_ml.optim import adam, cosine_schedule + + fixed = adam(learning_rate=3e-4) + scheduled = adam(learning_rate=cosine_schedule(3e-4, total_steps=10_000)) +""" def to_floatx(value: Rate) -> Rate: @@ -59,6 +178,17 @@ def to_floatx(value: Rate) -> Rate: ---------- value : float or TensorVariable A scalar a rule is about to build into its step. + + Examples + -------- + Cast a rate to ``floatX`` so it cannot silently upcast a float32 graph to float64. A symbolic rate, such + as one a schedule produced, passes through unchanged: + + .. code-block:: python + + from pytensor_ml.optim import to_floatx + + rate = to_floatx(1e-3) """ return value.astype(pytensor.config.floatX) if isinstance(value, Variable) else value @@ -79,8 +209,26 @@ def get_gradients( Returns ------- - list of TensorVariable + gradients : list of TensorVariable One gradient per parameter, in the order of ``parameters``. + + Examples + -------- + Take gradients of a loss with respect to the parameters, or pass gradients straight through. Every rule + calls it first, so a rule can be handed gradients you computed yourself: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import get_gradients + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + parameters = collect_trainable_params(loss) + gradients = get_gradients(loss, parameters) """ if isinstance(loss_or_gradients, list | tuple): gradients = list(loss_or_gradients) @@ -220,6 +368,17 @@ def scalar_state(name: str, fill_value: float = 0.0) -> Parameter: Name of the variable, used to match it at serialization boundaries. fill_value : float Value to initialize it with. Default 0.0. + + Examples + -------- + Build the scalar a rule or policy keeps between steps. Naming it makes it findable in a checkpoint and + in a printed graph: + + .. code-block:: python + + from pytensor_ml.optim import scalar_state + + scale = scalar_state("plateau/scale", fill_value=1.0) """ return _reuse_or_allocate( name, @@ -291,8 +450,27 @@ def chain(head, *rest: Transform): Returns ------- - UpdateRule or Transform + chained : UpdateRule or Transform A callable matching the head, applying every argument in sequence. + + Examples + -------- + Compose a rule with the transforms that follow it. The head decides the result: given a rule, the + whole chain is a rule, applied left to right: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, chain, clip_by_global_norm, compile_train, scale + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1e-3), clip_by_global_norm(1.0), scale(0.5))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state diff --git a/pytensor_ml/optim/clipping.py b/pytensor_ml/optim/clipping.py index 61bf1af..2236137 100644 --- a/pytensor_ml/optim/clipping.py +++ b/pytensor_ml/optim/clipping.py @@ -20,8 +20,27 @@ def clip_by_global_norm(max_norm: float = 1.0) -> Transform: Returns ------- - Transform + transform : Transform A transform that clips the updates dict by global norm. + + Examples + -------- + Bound the whole update rather than each coordinate, so the direction of the step survives and only + its magnitude is capped: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, chain, clip_by_global_norm, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1e-3), clip_by_global_norm(1.0))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ def transform(updates: Updates, parameters: Sequence[Parameter]) -> Updates: @@ -49,8 +68,27 @@ def clip_by_value(min_value: float = -1.0, max_value: float = 1.0) -> Transform: Returns ------- - Transform + transform : Transform A transform that clips the updates dict element-wise. + + Examples + -------- + Clip each coordinate on its own, which bounds the step but tilts its direction whenever only some + coordinates are clipped: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, chain, clip_by_value, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1e-3), clip_by_value(-0.1, 0.1))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ def transform(updates: Updates, parameters: Sequence[Parameter]) -> Updates: diff --git a/pytensor_ml/optim/guards.py b/pytensor_ml/optim/guards.py index ba86a8b..16aa1c7 100644 --- a/pytensor_ml/optim/guards.py +++ b/pytensor_ml/optim/guards.py @@ -16,8 +16,35 @@ ) from pytensor_ml.params import StepCounter -# Reads the step a rule has proposed and returns a scalar boolean graph: True to throw the step away. type Decision = Callable[[Updates, Sequence[Parameter]], TensorVariable] +""" +Reads the step a rule has proposed and returns a scalar boolean graph: True to throw the step away. + +Examples +-------- +Pass one straight to :func:`skip_if` when the reason a raised error names does not matter, or wrap it in +a :class:`SkipCondition` when it does: + +.. code-block:: python + + import numpy as np + import pytensor.tensor as pt + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, compile_train, skip_if + + + def loss_is_huge(updates, parameters): + return pt.max([pt.abs(updates[parameter]).max() for parameter in parameters]) > 1e6 + + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, skip_if(adam(1e-3), loss_is_huge)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) +""" @dataclass(frozen=True) @@ -32,6 +59,30 @@ class SkipCondition: reason : str Phrase naming why this condition skips, completing the sentence "the optimizer ..." in the error a run of consecutive skips raises. Default names no particular cause. + + Examples + -------- + Pair a decision graph with the reason a raised error should name, for a condition of your own: + + .. code-block:: python + + import numpy as np + import pytensor.tensor as pt + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import SkipCondition, adam, compile_train, skip_if + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + any_step_huge = SkipCondition( + decide=lambda updates, parameters: pt.max([pt.abs(step).max() for step in updates.values()]) > 1e3, + reason="took a step with an implausibly large coordinate", + ) + + step = compile_train(loss, skip_if(adam(1e-3), any_step_huge)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ decide: Decision @@ -53,6 +104,25 @@ def nonfinite() -> SkipCondition: :func:`~pytensor_ml.optim.policy.reduce_on_plateau` holds an infinite best-loss until it has seen a full window -- and that is not a step to throw away. Optimizer state cannot hide a NaN for long in any case, since a poisoned moment reaches its parameter on the very next step. + + Examples + -------- + The condition behind :func:`apply_if_finite`, useful when you want it alongside a different skip budget + than that helper's default: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, compile_train, nonfinite, skip_if + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, skip_if(adam(1e-3), nonfinite(), max_consecutive_skips=None)) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ def decide(updates: Updates, parameters: Sequence[Parameter]) -> TensorVariable: @@ -88,6 +158,25 @@ def large_step(max_norm: float) -> SkipCondition: ---------- max_norm : float Norm at which a step is thrown away rather than applied. + + Examples + -------- + Skip a step whose global norm exceeds a bound. Unlike :func:`clip_by_global_norm`, which rescales an + outsized step and applies it, this one discards it entirely: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, compile_train, large_step, skip_if + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, skip_if(adam(1e-3), large_step(10.0))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ if max_norm <= 0.0: raise ValueError( @@ -160,8 +249,30 @@ def skip_if( Returns ------- - UpdateRule + guarded_rule : UpdateRule The guarded rule, which also writes both skip counters. + + Examples + -------- + Wrap a rule to throw away any step meeting the condition, leaving the parameters where they were. It + raises once too many steps in a row are skipped, so a divergence surfaces instead of looking like + training that quietly stopped learning: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, compile_train, large_step, skip_if + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + rule = skip_if(adam(1e-3), large_step(10.0), max_consecutive_skips=3) + + step = compile_train(loss, rule) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ if max_consecutive_skips is not None and max_consecutive_skips < 1: raise ValueError( @@ -227,6 +338,25 @@ def apply_if_finite( :func:`skip_if` under :func:`nonfinite`, which is the common case and the name optax gives it. Takes the same keyword arguments; see :func:`skip_if` for what they mean and what the guard does and does not cover. + + Examples + -------- + The common case of :func:`skip_if`: drop any step carrying a NaN or an infinity, which would otherwise + poison every parameter it touches and every step after it: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, apply_if_finite, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, apply_if_finite(adam(1e-3))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ return skip_if( rule, diff --git a/pytensor_ml/optim/policy.py b/pytensor_ml/optim/policy.py index 7c0de6e..6c4ec52 100644 --- a/pytensor_ml/optim/policy.py +++ b/pytensor_ml/optim/policy.py @@ -67,8 +67,31 @@ def reduce_on_plateau( Returns ------- - UpdateRule + wrapped_rule : UpdateRule The wrapped rule, which also writes the scale and the policy's own history. + + Examples + -------- + Own a scale the rule's rate is built from, and the policy cuts it once the loss stops improving. It + decides once per step rather than once per epoch, so widen ``accumulation_size`` to judge on a window + of batches rather than on a single noisy one: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, compile_train, reduce_on_plateau, scalar_state + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + scale = scalar_state("plateau/scale", fill_value=1.0) + rule = reduce_on_plateau(adam(learning_rate=scale * 1e-3), scale, patience=5, accumulation_size=50) + + step = compile_train(loss, rule) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ if not 0.0 < factor < 1.0: raise ValueError(f"factor must lie in (0, 1), got {factor}.") diff --git a/pytensor_ml/optim/rules.py b/pytensor_ml/optim/rules.py index 8a1dfe2..b476189 100644 --- a/pytensor_ml/optim/rules.py +++ b/pytensor_ml/optim/rules.py @@ -41,8 +41,30 @@ def sgd_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter to its next value. + + Examples + -------- + The update function behind :func:`sgd`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly, and its rate defaults to 1.0 rather than the alias's 0.01: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import sgd_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = sgd_updates(loss, collect_trainable_params(loss), learning_rate=0.1) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ gradients = get_gradients(loss_or_gradients, parameters) learning_rate = to_floatx(learning_rate) @@ -90,8 +112,30 @@ def adam_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its moment buffers to their next values. + + Examples + -------- + The update function behind :func:`adam`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = adam_updates(loss, collect_trainable_params(loss), learning_rate=1e-3) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ return _adam_family_updates( loss_or_gradients, @@ -239,8 +283,30 @@ def adamw_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its moment buffers to their next values. + + Examples + -------- + The update function behind :func:`adamw`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly, decoupling the weight decay from the adaptive rate: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adamw_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = adamw_updates(loss, collect_trainable_params(loss), learning_rate=1e-3, weight_decay=0.01) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ return _adam_family_updates( loss_or_gradients, @@ -292,8 +358,30 @@ def nadam_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its moment buffers to their next values. + + Examples + -------- + The update function behind :func:`nadam`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import nadam_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = nadam_updates(loss, collect_trainable_params(loss), learning_rate=2e-3) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ gradients = get_gradients(loss_or_gradients, parameters) learning_rate = to_floatx(learning_rate) @@ -361,8 +449,30 @@ def adamax_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its state buffers to their next values. + + Examples + -------- + The update function behind :func:`adamax`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adamax_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = adamax_updates(loss, collect_trainable_params(loss), learning_rate=2e-3) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ gradients = get_gradients(loss_or_gradients, parameters) learning_rate = to_floatx(learning_rate) @@ -416,8 +526,30 @@ def adagrad_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its accumulator to their next values. + + Examples + -------- + The update function behind :func:`adagrad`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adagrad_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = adagrad_updates(loss, collect_trainable_params(loss), learning_rate=1e-2) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ gradients = get_gradients(loss_or_gradients, parameters) learning_rate = to_floatx(learning_rate) @@ -474,8 +606,30 @@ def rmsprop_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its state buffers to their next values. + + Examples + -------- + The update function behind :func:`rmsprop`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import rmsprop_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = rmsprop_updates(loss, collect_trainable_params(loss), learning_rate=1e-2) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ gradients = get_gradients(loss_or_gradients, parameters) learning_rate = to_floatx(learning_rate) @@ -538,8 +692,30 @@ def adadelta_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its two accumulators to their next values. + + Examples + -------- + The update function behind :func:`adadelta`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly, needing no learning rate of its own: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adadelta_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = adadelta_updates(loss, collect_trainable_params(loss)) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ gradients = get_gradients(loss_or_gradients, parameters) learning_rate = to_floatx(learning_rate) @@ -625,8 +801,30 @@ def rprop_updates( Returns ------- - Updates + updates : Updates Mapping from each parameter and its state buffers to their next values. + + Examples + -------- + The update function behind :func:`rprop`, for driving a bare ``pytensor.function`` yourself rather + than going through :func:`~pytensor_ml.optim.train.compile_train`. It returns the updates dict directly, stepping by gradient sign alone: + + .. code-block:: python + + import numpy as np + import pytensor + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import rprop_updates + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + updates = rprop_updates(loss, collect_trainable_params(loss), learning_rate=1e-2) + step = pytensor.function([X, target], loss, updates=updates) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ _require_numeric_learning_rate(learning_rate) diff --git a/pytensor_ml/optim/schedules.py b/pytensor_ml/optim/schedules.py index 182cddf..ab7b13d 100644 --- a/pytensor_ml/optim/schedules.py +++ b/pytensor_ml/optim/schedules.py @@ -60,7 +60,7 @@ def cosine_schedule( Returns ------- - Schedule + schedule : Schedule A callable mapping a symbolic step count to a scalar learning rate, ready to hand to a rule as its ``learning_rate``. @@ -124,9 +124,19 @@ def linear_schedule( Returns ------- - Schedule + schedule : Schedule A callable mapping a symbolic step count to a scalar learning rate, ready to hand to a rule as its ``learning_rate``. + + Examples + -------- + Move the rate along a straight line, the usual choice for a warmup or a linear decay to zero: + + .. code-block:: python + + from pytensor_ml.optim import adam, linear_schedule + + rule = adam(learning_rate=linear_schedule(3e-4, total_steps=10_000, final_learning_rate=1e-5)) """ _validate_horizon(total_steps, transition_begin) @@ -178,9 +188,20 @@ def exponential_schedule( Returns ------- - Schedule + schedule : Schedule A callable mapping a symbolic step count to a scalar learning rate, ready to hand to a rule as its ``learning_rate``. + + Examples + -------- + Decay by a constant factor per step, so the rate falls fast early and flattens out. Both endpoints + must be positive, since no finite number of multiplications reaches zero: + + .. code-block:: python + + from pytensor_ml.optim import adam, exponential_schedule + + rule = adam(learning_rate=exponential_schedule(3e-4, total_steps=10_000, final_learning_rate=1e-6)) """ _validate_horizon(total_steps, transition_begin) if final_learning_rate <= 0.0 or learning_rate <= 0.0: @@ -241,9 +262,20 @@ def polynomial_schedule( Returns ------- - Schedule + schedule : Schedule A callable mapping a symbolic step count to a scalar learning rate, ready to hand to a rule as its ``learning_rate``. + + Examples + -------- + Bend the path between the endpoints: ``power=1.0`` is linear, higher powers hold the initial rate + longer before dropping away: + + .. code-block:: python + + from pytensor_ml.optim import adam, polynomial_schedule + + rule = adam(learning_rate=polynomial_schedule(3e-4, total_steps=10_000, power=2.0)) """ _validate_horizon(total_steps, transition_begin) if power <= 0.0: @@ -299,9 +331,20 @@ def step_decay( Returns ------- - Schedule + schedule : Schedule A callable mapping a symbolic step count to a scalar learning rate, ready to hand to a rule as its ``learning_rate``. + + Examples + -------- + Cut the rate by a factor on a fixed cadence, holding it flat in between -- the staircase familiar + from torch's ``StepLR``: + + .. code-block:: python + + from pytensor_ml.optim import adam, step_decay + + rule = adam(learning_rate=step_decay(3e-4, decay_every=2_000, decay_factor=0.5)) """ if decay_every < 1: raise ValueError(f"decay_every must be at least 1, got {decay_every}.") @@ -336,9 +379,20 @@ def constant_schedule(learning_rate: float) -> Schedule: Returns ------- - Schedule + schedule : Schedule A callable mapping a symbolic step count to a scalar learning rate, ready to hand to a rule as its ``learning_rate``. + + Examples + -------- + Hold one rate for the whole run. Useful as a segment of :func:`join_schedules`, where every other + segment is a schedule too: + + .. code-block:: python + + from pytensor_ml.optim import adam, constant_schedule + + rule = adam(learning_rate=constant_schedule(3e-4)) """ def schedule(step_count: TensorVariable) -> TensorVariable: @@ -373,9 +427,23 @@ def join_schedules(schedules: Sequence[Schedule], boundaries: Sequence[int]) -> Returns ------- - Schedule + schedule : Schedule A callable mapping a symbolic step count to a scalar learning rate, ready to hand to a rule as its ``learning_rate``. + + Examples + -------- + Run schedules back to back, switching at each boundary step. A linear warmup into a cosine decay is + the standard recipe for a transformer: + + .. code-block:: python + + from pytensor_ml.optim import adam, cosine_schedule, join_schedules, linear_schedule + + warmup = linear_schedule(0.0, total_steps=1_000, final_learning_rate=3e-4) + decay = cosine_schedule(3e-4, total_steps=9_000) + + rule = adam(learning_rate=join_schedules([warmup, decay], boundaries=[1_000])) """ if not schedules: raise ValueError("join_schedules needs at least one schedule.") diff --git a/pytensor_ml/optim/train.py b/pytensor_ml/optim/train.py index 53c750a..86b157e 100644 --- a/pytensor_ml/optim/train.py +++ b/pytensor_ml/optim/train.py @@ -82,6 +82,27 @@ def compile_train( step : Function The compiled one-step training function, applying every update in place. Returns the loss alone, or ``(loss, *extra_outputs)`` when diagnostics were requested. + + Examples + -------- + Hand it any scalar loss graph and a rule, and it differentiates the loss, applies the rule, and folds in + every update the graph carries -- optimizer state, batch-norm statistics, RNGs, training clocks. Pass + ``extra_outputs`` to read a value out alongside the loss: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, compile_train + + X = Input("X", shape=(None, 4)) + prediction = Linear("fc", n_in=4, n_out=1)(X) + loss, target = supervised_loss(prediction, SquaredError(), ndim_out=2) + + step = compile_train(loss, adam(1e-3), inputs=[X, target], extra_outputs=[prediction]) + loss_value, predictions = step(np.zeros((8, 4)), np.zeros((8, 1))) """ extra_outputs = list(extra_outputs or []) extra_updates = dict(extra_updates or {}) diff --git a/pytensor_ml/optim/transform.py b/pytensor_ml/optim/transform.py index 36244cb..3e79248 100644 --- a/pytensor_ml/optim/transform.py +++ b/pytensor_ml/optim/transform.py @@ -29,8 +29,26 @@ def trace(decay: float = 0.9, nesterov: bool = False) -> Transform: Returns ------- - Transform + transform : Transform A transform that folds momentum into the updates dict. + + Examples + -------- + Fold momentum into whatever produced the steps, giving a rule that has none of its own: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import chain, compile_train, sgd, trace + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(sgd(0.1), trace(decay=0.9, nesterov=True))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ def transform(updates: Updates, parameters: Sequence[Parameter]) -> Updates: @@ -61,8 +79,27 @@ def scale(factor: Rate) -> Transform: Returns ------- - Transform + transform : Transform A transform that rescales the updates dict. + + Examples + -------- + Multiply every step by a constant, most often to shrink a rule's steps without rebuilding it at a + different rate: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, chain, compile_train, scale + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1e-3), scale(0.5))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ def transform(updates: Updates, parameters: Sequence[Parameter]) -> Updates: @@ -104,8 +141,27 @@ def scale_by_schedule(schedule: Schedule, *, namespace: str = "scale_by_schedule Returns ------- - Transform + transform : Transform A transform that rescales the updates dict by the rate its clock currently reads. + + Examples + -------- + Apply the rate at the end of a chain rather than inside the rule, so a clip placed before it bounds + the step in gradient units instead of units that move with the rate: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, chain, clip_by_global_norm, compile_train, cosine_schedule, scale_by_schedule + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1.0), clip_by_global_norm(1.0), scale_by_schedule(cosine_schedule(3e-4, 10_000)))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ @reuses_state @@ -136,8 +192,27 @@ def add_weight_decay( Returns ------- - Transform + transform : Transform A transform that folds weight decay into the updates dict. + + Examples + -------- + Pull weights towards zero by a fixed fraction of themselves each step, independently of the + gradient. The mask keeps biases and norm scales out of it: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.loss import SquaredError, supervised_loss + from pytensor_ml.optim import adam, add_weight_decay, chain, compile_train + + X = Input("X", shape=(None, 4)) + loss, target = supervised_loss(Linear("fc", n_in=4, n_out=1)(X), SquaredError(), ndim_out=2) + + step = compile_train(loss, chain(adam(1e-3), add_weight_decay(0.01, mask=lambda parameter: parameter.ndim > 1))) + loss_value = step(np.zeros((8, 4)), np.zeros((8, 1))) """ def transform(updates: Updates, parameters: Sequence[Parameter]) -> Updates: diff --git a/pytensor_ml/params.py b/pytensor_ml/params.py index 0662206..b366d47 100644 --- a/pytensor_ml/params.py +++ b/pytensor_ml/params.py @@ -20,17 +20,68 @@ class TrainableParameter(TensorSharedVariable): The law this parameter's value is drawn from, which :func:`~pytensor_ml.state.initialize_params` redraws it from. Every layer declares one for each parameter it builds. None means a redraw has nothing to go on and raises. + + Examples + -------- + The shared-variable class :func:`trainable` produces. Graph traversal tells parameters apart by type, + which is how an optimizer finds exactly the weights it may write: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.params import TrainableParameter, trainable + from pytensor_ml.pytensorf import collect_trainable_params + from pytensor_ml.state import ZeroInitializer + + W = trainable(np.zeros((4, 4)), "W", initializer=ZeroInitializer()) + + is_trainable = isinstance(W, TrainableParameter) + found = collect_trainable_params(W.sum()) """ initializer: "Initializer | None" = None class NonTrainableParameter(TensorSharedVariable): - """Marker class for non-trainable state (running mean/var in BatchNorm).""" + """ + Marker class for non-trainable state (running mean/var in BatchNorm). + + Examples + -------- + The shared-variable class :func:`non_trainable` produces. The separate type is what keeps a running + statistic out of the set an optimizer differentiates and writes: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.params import NonTrainableParameter, non_trainable + + running_mean = non_trainable(np.zeros(32), "bn_running_mean") + + is_non_trainable = isinstance(running_mean, NonTrainableParameter) + """ class StepCounter(TensorSharedVariable): - """Training time: an integer scalar counting training steps, whose transition is :meth:`advance`.""" + """ + Training time: an integer scalar counting training steps, whose transition is :meth:`advance`. + + Examples + -------- + The shared-variable class :func:`step_counter` produces. Its type is how + :func:`~pytensor_ml.pytensorf.collect_clock_updates` finds every clock in a graph and writes each one's + advance into the compiled step: + + .. code-block:: python + + from pytensor_ml.params import StepCounter, step_counter + + clock = step_counter("step_count") + + is_clock = isinstance(clock, StepCounter) + """ def advance(self) -> TensorVariable: """Return the expression for this counter's value on the next training step.""" @@ -78,6 +129,20 @@ def trainable( draw. Default None, which leaves the parameter with no law and raises on a redraw. **kwargs Additional arguments passed to the SharedVariable constructor. + + Examples + -------- + Declare a weight an optimizer may write. Name it, since optimizer state and checkpoints are matched by + name, and give it the initializer it should be redrawn from: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.params import trainable + from pytensor_ml.state import XavierUniformInitializer + + W = trainable(np.zeros((64, 32)), "fc_W", initializer=XavierUniformInitializer()) """ parameter = _make_parameter(TrainableParameter, value, name, shape, strict, **kwargs) parameter.initializer = initializer @@ -114,6 +179,19 @@ def non_trainable(value, name=None, shape=None, strict=False, **kwargs) -> NonTr Takes the same arguments as :func:`trainable`; only the marker class differs, which is what keeps these out of the set an optimizer updates. + + Examples + -------- + Declare state the model owns but no optimizer may write, which is what a batch-norm running mean is. + It still travels in a checkpoint and still gets restored: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.params import non_trainable + + running_mean = non_trainable(np.zeros(32), "bn_running_mean") """ return _make_parameter(NonTrainableParameter, value, name, shape, strict, **kwargs) @@ -132,6 +210,19 @@ def step_counter(name: str = "step_count") -> StepCounter: name : str, optional Name for the counter. Training state is matched by name at serialization boundaries. Default 'step_count'. + + Examples + -------- + Build the clock a schedule reads. Every clock in a graph counts the same steps, and the compiled + function advances them, so a schedule moves through time rather than reading step zero forever: + + .. code-block:: python + + from pytensor_ml.optim import cosine_schedule + from pytensor_ml.params import step_counter + + clock = step_counter("my_schedule/step_count") + rate = cosine_schedule(3e-4, total_steps=10_000)(clock) """ return _make_parameter( StepCounter, np.asarray(0, dtype="int64"), name, shape=None, strict=False diff --git a/pytensor_ml/pretrained.py b/pytensor_ml/pretrained.py index c091867..ccbd5d3 100644 --- a/pytensor_ml/pretrained.py +++ b/pytensor_ml/pretrained.py @@ -195,6 +195,22 @@ def save_network( inputs : sequence of Variable, optional The network's data inputs, in call order. Collected from ``outputs`` when omitted; pass explicitly when call order matters. + + Examples + -------- + Write the architecture alone, as JSON. The weights are not in it, so pair it with + :func:`~pytensor_ml.checkpoint.save_state` or use :func:`save_pretrained`, which writes both. + The destination directory has to exist already: + + .. code-block:: python + + from pytensor_ml import save_network + from pytensor_ml.layers import Input, Linear + + X = Input("X", shape=(None, 64)) + logits = Linear("logits", n_in=64, n_out=10)(X) + + save_network(logits, "config.json") """ output_list = as_output_list(outputs) data_inputs = list(inputs) if inputs is not None else collect_data_inputs(output_list) @@ -236,6 +252,21 @@ def load_network( The network's data inputs, in call order. outputs : Variable or list of Variable The rebuilt output(s) -- a single variable when the network has one output, otherwise a list. + + Examples + -------- + Rebuild a saved architecture with freshly drawn weights, which is what you want when the values are + about to be trained or loaded separately: + + .. code-block:: python + + from pytensor_ml import load_network, save_network + from pytensor_ml.layers import Input, Linear + + X = Input("X", shape=(None, 64)) + save_network(Linear("logits", n_in=64, n_out=10)(X), "config.json") + + inputs, outputs = load_network("config.json") """ config = json.loads(Path(path).read_text()) if config.get("format") != GRAPH_FORMAT: @@ -283,6 +314,29 @@ def save_pretrained( Destination directory, created if needed. inputs : sequence of Variable, optional The network's data inputs, in call order. Collected from ``outputs`` when omitted. + + Examples + -------- + Write the architecture and the weights together, so the directory reloads into a runnable network + without the Python that defined it: + + .. code-block:: python + + from pytensor_ml import save_pretrained + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import Input, Linear, Sequential + from pytensor_ml.model import Model + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + ReLU(), + Linear("logits", n_in=32, n_out=10), + ) + logits = network(X) + Model(X, logits).initialize(seed=0) + + save_pretrained(logits, "artifacts/model") """ directory = Path(directory) directory.mkdir(parents=True, exist_ok=True) @@ -315,6 +369,28 @@ def from_pretrained( The network's data inputs, in call order. outputs : Variable or list of Variable The rebuilt, weight-filled output(s). + + Examples + -------- + Rebuild a saved network and fill its weights, returning the data inputs and the outputs. Nothing that + defined the network has to be importable: + + .. code-block:: python + + import numpy as np + + from pytensor_ml import from_pretrained, save_pretrained + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.pytensorf import function + + X = Input("X", shape=(None, 64)) + logits = Linear("logits", n_in=64, n_out=10)(X) + Model(X, logits).initialize(seed=0) + save_pretrained(logits, "artifacts/model") + + inputs, outputs = from_pretrained("artifacts/model") + predictions = function(inputs, outputs)(np.zeros((4, 64))) """ directory = Path(directory) if source_format == "auto": diff --git a/pytensor_ml/pytensorf/collect.py b/pytensor_ml/pytensorf/collect.py index f984e5d..04c032e 100644 --- a/pytensor_ml/pytensorf/collect.py +++ b/pytensor_ml/pytensorf/collect.py @@ -13,7 +13,24 @@ def as_output_list(outputs: Variable | Sequence[Variable]) -> list[Variable]: - """Normalize one output, or a sequence of them, to a list.""" + """ + Normalize one output, or a sequence of them, to a list. + + Examples + -------- + Normalize an output argument that may be one variable or a sequence of them, so the code after it has + one shape to handle: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.pytensorf import as_output_list + + X = Input("X", shape=(None, 64)) + activations = Linear("fc", n_in=64, n_out=32)(X) + + outputs = as_output_list(activations) + """ return [outputs] if isinstance(outputs, Variable) else list(outputs) @@ -30,7 +47,33 @@ def _collect_inputs_of_type[T: Variable]( def collect_graph_inputs(outputs: Variable | Sequence[Variable]) -> list[Variable]: - """Collect the graph inputs that carry data -- everything that is neither a Constant nor shared.""" + """ + Collect the graph inputs that carry data -- everything that is neither a Constant nor shared. + + Examples + -------- + The placeholders a caller has to supply, in the order the graph puts them. Weights, running + statistics and RNGs are shared, so they are left out -- the compiled function carries those itself. + :func:`collect_data_inputs` is the same function under the name the training and serialization + boundaries use: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import collect_graph_inputs + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5, random_state=0), + ) + activations = network(X) + + inputs = collect_graph_inputs(activations) + """ return [ variable for variable in graph_inputs(as_output_list(outputs)) @@ -43,12 +86,60 @@ def collect_graph_inputs(outputs: Variable | Sequence[Variable]) -> list[Variabl def collect_shared_variables(outputs: Variable | Sequence[Variable]) -> list[SharedVariable]: - """Collect every SharedVariable the graph reads, parameters and RNGs alike.""" + """ + Collect every SharedVariable the graph reads, parameters and RNGs alike. + + Examples + -------- + Every shared variable in the graph, whichever kind: parameters, running statistics, RNGs and + training clocks together. This is the set a checkpoint saves: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import collect_shared_variables + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5, random_state=0), + ) + activations = network(X) + + shared = collect_shared_variables(activations) + """ return _collect_inputs_of_type(outputs, SharedVariable) def collect_trainable_params(outputs: Variable | Sequence[Variable]) -> list[TrainableParameter]: - """Collect the parameters an optimizer should update.""" + """ + Collect the parameters an optimizer should update. + + Examples + -------- + The weights an optimizer is allowed to write. This is what a rule differentiates with respect to, + and what :meth:`~pytensor_ml.model.Model.initialize` redraws: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import collect_trainable_params + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5, random_state=0), + ) + activations = network(X) + + parameters = collect_trainable_params(activations) + """ return _collect_inputs_of_type(outputs, TrainableParameter) @@ -75,8 +166,30 @@ def collect_differentiable_params( Returns ------- - list of TrainableParameter + parameters : list of TrainableParameter The differentiable parameters, in graph-input order. + + Examples + -------- + The trainable parameters the loss actually depends on. A parameter reached only through a + non-differentiable path is left out, since asking for its gradient would raise: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import collect_differentiable_params + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5, random_state=0), + ) + activations = network(X) + + parameters = collect_differentiable_params(activations) """ output_list = as_output_list(outputs) stop_gradient_outputs = [ @@ -101,12 +214,60 @@ def collect_differentiable_params( def collect_non_trainable_params( outputs: Variable | Sequence[Variable], ) -> list[NonTrainableParameter]: - """Collect the state that training updates without gradients, such as batch-norm running statistics.""" + """ + Collect the state that training updates without gradients, such as batch-norm running statistics. + + Examples + -------- + State the model owns but no optimizer may write, such as a batch-norm running mean. The model + updates these from its own forward pass: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import collect_non_trainable_params + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5, random_state=0), + ) + activations = network(X) + + statistics = collect_non_trainable_params(activations) + """ return _collect_inputs_of_type(outputs, NonTrainableParameter) def collect_step_counters(outputs: Variable | Sequence[Variable]) -> list[StepCounter]: - """Collect the training clocks the graph reads.""" + """ + Collect the training clocks the graph reads. + + Examples + -------- + The training clocks the graph reads. Each counts steps for a schedule, and every one in a graph + counts the same steps: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import collect_step_counters + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5, random_state=0), + ) + activations = network(X) + + clocks = collect_step_counters(activations) + """ return _collect_inputs_of_type(outputs, StepCounter) @@ -134,6 +295,27 @@ def collect_clock_updates( ------- clock_updates : dict Mapping from each clock the graph reads to the expression for its next value. + + Examples + -------- + The one-step advance for each training clock in the graph, which is what makes a schedule move rather + than read step zero forever. :func:`function` threads these in automatically: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.optim import cosine_schedule, get_gradients, scale_by_schedule + from pytensor_ml.pytensorf import collect_clock_updates, collect_trainable_params + + X = Input("X", shape=(None, 64)) + activations = Linear("fc", n_in=64, n_out=32)(X) + + parameters = collect_trainable_params(activations) + updates = scale_by_schedule(cosine_schedule(1e-3, 1_000))( + dict(zip(parameters, get_gradients(activations.sum(), parameters))), parameters + ) + + clock_updates = collect_clock_updates(list(updates.values())) """ counters = [ counter for counter in collect_step_counters(outputs) if counter not in already_written @@ -165,6 +347,28 @@ def collect_non_trainable_updates( non_trainable_updates : dict Mapping from each NonTrainableParameter to its new value, for every update an op declares through :meth:`~pytensor_ml.base.StatefulOp.update_map`. + + Examples + -------- + The writes the model makes on its own, such as a batch-norm statistic, mapped to their next values. + :func:`~pytensor_ml.optim.train.compile_train` folds these in alongside the rule's own updates: + + .. code-block:: python + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import collect_non_trainable_updates + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5, random_state=0), + ) + activations = network(X) + + updates = collect_non_trainable_updates(activations) """ updates: dict[NonTrainableParameter, TensorVariable] = {} for ancestor in ancestors(as_output_list(outputs)): diff --git a/pytensor_ml/pytensorf/compile.py b/pytensor_ml/pytensorf/compile.py index f1cd0ea..cb6841f 100644 --- a/pytensor_ml/pytensorf/compile.py +++ b/pytensor_ml/pytensorf/compile.py @@ -52,8 +52,31 @@ def function( Returns ------- - Function + compiled_function : Function The compiled function. + + Examples + -------- + Compile like ``pytensor.function``, with the RNG and training-clock updates threaded in, so repeated + calls advance their state instead of repeating the first draw. Pass ``random_seed`` to make the draws + reproducible: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import function + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + Dropout(p=0.5), + ) + activations = network(X) + + forward = function([X], activations, random_seed=0) + first, second = forward(np.zeros((4, 64))), forward(np.zeros((4, 64))) """ updates = dict(kwargs.pop("updates", {})) input_variables = [inp.variable if isinstance(inp, pytensor.In) else inp for inp in inputs] @@ -144,8 +167,35 @@ def compile_predict( Returns ------- - Function + predict_function : Function The compiled prediction function. + + Examples + -------- + Compile the inference pass: dropout is removed and batch norm reads its running statistics, so the + result is deterministic and independent of the rest of the batch: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.activations import ReLU + from pytensor_ml.layers import BatchNorm, Dropout, Input, Linear, Sequential + from pytensor_ml.model import Model + from pytensor_ml.pytensorf import compile_predict + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + BatchNorm("bn", n_in=32), + ReLU(), + Dropout(p=0.5), + ) + activations = network(X) + Model(X, activations).initialize(seed=0) + + predict = compile_predict(activations, inputs=[X]) + predictions = predict(np.zeros((4, 64))) """ specialized = rewrite_for_prediction(prediction) if inputs is None: diff --git a/pytensor_ml/pytensorf/rewrite.py b/pytensor_ml/pytensorf/rewrite.py index ea972a0..a557b19 100644 --- a/pytensor_ml/pytensorf/rewrite.py +++ b/pytensor_ml/pytensorf/rewrite.py @@ -19,7 +19,7 @@ def hoist_scan_draws(outputs): Returns ------- - list of Variable + rewritten : list of Variable The rewritten graphs, in the order given. """ fgraph = FunctionGraph(outputs=list(outputs), clone=True, copy_inputs=False) @@ -35,6 +35,21 @@ def rewrite_pregrad(graph): ``graph`` still reaches ``grad``. Lifts a draw written inside a scan out of the loop, which :func:`grad` needs rather than merely tolerates: a draw inside the differentiated region leaves no fixed sample to take a gradient against, and scan reports it as an undefined gradient. + + Examples + -------- + Apply the rewrites that have to run before differentiation, which is what every rule does to a loss + before taking its gradient: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.pytensorf import rewrite_pregrad + + X = Input("X", shape=(None, 64)) + loss = Linear("fc", n_in=64, n_out=32)(X).sum() + + prepared = rewrite_pregrad(loss) """ simplified = rewrite_graph( graph, include=("canonicalize", "stabilize"), exclude=("local_view_op",) @@ -54,9 +69,28 @@ def rewrite_for_prediction(graph): Returns ------- - FunctionGraph, Variable, or list of Variable + specialized_graph : FunctionGraph, Variable, or list of Variable The specialized graph, matching the form of ``graph``. A FunctionGraph is rewritten in place and returned; a Variable or sequence is rewritten on a clone, leaving the original untouched. + + Examples + -------- + Specialize a training graph for inference without compiling it, which is what :func:`compile_predict` + does first. A Variable or a sequence is rewritten on a clone, leaving the original untouched: + + .. code-block:: python + + from pytensor_ml.layers import Dropout, Input, Linear, Sequential + from pytensor_ml.pytensorf import rewrite_for_prediction + + X = Input("X", shape=(None, 64)) + network = Sequential( + Linear("fc", n_in=64, n_out=32), + Dropout(p=0.5), + ) + activations = network(X) + + inference_graph = rewrite_for_prediction(activations) """ # Local by design, matching pytensor's own op/rewrite pattern: the rewrites import the layer ops they # match on, so a module-scope import would tie this module to the whole layer surface. diff --git a/pytensor_ml/pytensorf/rng.py b/pytensor_ml/pytensorf/rng.py index 5595648..10b5bc4 100644 --- a/pytensor_ml/pytensorf/rng.py +++ b/pytensor_ml/pytensorf/rng.py @@ -30,7 +30,24 @@ def atleast_list(x): # Scan, and OpFromGraph between inputs and outputs, so a compiled function advances its generators instead # of repeating draws. def find_rng_nodes(variables: Iterable[Variable]) -> list[RandomGeneratorSharedVariable]: - """Return the shared RNG variables in a graph.""" + """ + Return the shared RNG variables in a graph. + + Examples + -------- + Locate the random generators a graph draws from, which is what a dropout layer or any other sampling op + leaves behind: + + .. code-block:: python + + from pytensor_ml.layers import Dropout, Input + from pytensor_ml.pytensorf import find_rng_nodes + + X = Input("X", shape=(None, 64)) + activations = Dropout(p=0.5, random_state=0)(X) + + generators = find_rng_nodes([activations]) + """ return [ node for node in graph_inputs(variables) if isinstance(node, RandomGeneratorSharedVariable) ] @@ -63,7 +80,7 @@ def find_generators_drawn_from( Returns ------- - list of RandomGeneratorSharedVariable + generators : list of RandomGeneratorSharedVariable The generators a draw op consumes, in graph-input order. """ fgraph = FunctionGraph(outputs=list(outputs), clone=False) @@ -110,7 +127,7 @@ def collect_default_updates( Returns ------- - dict mapping Variable to Variable + updates : dict mapping Variable to Variable Each RNG variable to the expression for its next state. """ diff --git a/pytensor_ml/rewriting/scan.py b/pytensor_ml/rewriting/scan.py index 0d1abc5..9b2823d 100644 --- a/pytensor_ml/rewriting/scan.py +++ b/pytensor_ml/rewriting/scan.py @@ -120,7 +120,7 @@ def hoist_draws_out_of_scan(fgraph: FunctionGraph, node: Apply) -> list[Variable Returns ------- - list of Variable or None + outputs : list of Variable or None The rebuilt scan's outputs, or None when the loop has no such draw. """ args = ScanArgs.from_node(node, clone=True) diff --git a/pytensor_ml/state.py b/pytensor_ml/state.py index aaad761..4569d72 100644 --- a/pytensor_ml/state.py +++ b/pytensor_ml/state.py @@ -30,6 +30,33 @@ class Initializer(ABC): ``__props__`` names the constructor arguments that define the draw, borrowing pytensor's Op convention so the same encoder serves both. A subclass taking arguments must list them, or a saved network rebuilds it with the defaults rather than the values it was built with. + + Examples + -------- + Subclass it to describe a draw of your own, or reach for the :func:`initializer` decorator, which builds + the class from a sampling function. ``__props__`` is what a saved config records, so a parameter that is + reloaded is drawn the same way: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.state import Initializer + + + class ConstantInitializer(Initializer): + __props__ = ("value",) + + def __init__(self, value=0.0): + self.value = value + + def sample(self, shape, dtype, rng): + return np.full(shape, self.value, dtype=dtype) + + + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=ConstantInitializer(0.5)) + activations = layer(Input("X", shape=(None, 64))) """ __props__: tuple[str, ...] = () @@ -64,16 +91,75 @@ def _sample_like(self, param: SharedVariable, rng: RandomState | None = None) -> class ZeroInitializer(Initializer): + """ + Fill every element with zero, the right draw for a bias or any additive offset. + + Examples + -------- + Layers already draw their biases this way; pass it explicitly to zero a weight matrix that would + otherwise be drawn at random: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.state import ZeroInitializer + + X = Input("X", shape=(None, 64)) + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=ZeroInitializer()) + + model = Model(X, layer(X)).initialize(seed=0) + """ + def sample(self, shape: tuple[int, ...], dtype: str, rng: np.random.Generator) -> np.ndarray: return np.zeros(shape, dtype=dtype) class OneInitializer(Initializer): + """ + Fill every element with one, the right draw for a multiplicative scale. + + Examples + -------- + The draw a normalization scale wants, so the layer starts as the identity transform: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.state import OneInitializer + + X = Input("X", shape=(None, 64)) + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=OneInitializer()) + + model = Model(X, layer(X)).initialize(seed=0) + """ + def sample(self, shape: tuple[int, ...], dtype: str, rng: np.random.Generator) -> np.ndarray: return np.ones(shape, dtype=dtype) class UnitUniformInitializer(Initializer): + r""" + Draw from :math:`\mathcal{U}(0, 1)`. + + Examples + -------- + Draws on the unit interval, which suits a parameter that is a probability or a fraction rather than + a weight: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.state import UnitUniformInitializer + + X = Input("X", shape=(None, 64)) + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=UnitUniformInitializer()) + + model = Model(X, layer(X)).initialize(seed=0) + """ + def sample(self, shape: tuple[int, ...], dtype: str, rng: np.random.Generator) -> np.ndarray: return rng.uniform(0.0, 1.0, size=shape).astype(dtype) @@ -92,6 +178,22 @@ class NormalInitializer(Initializer): Center of the distribution :math:`\mu`. Default 0.0. std : float Standard deviation :math:`\sigma`. Default 0.01. + + Examples + -------- + A fixed-width Gaussian, ignoring the parameter's shape. GPT-2 initializes this way at ``std=0.02``, + where a fan-scaled draw would widen as layers narrow: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.state import NormalInitializer + + X = Input("X", shape=(None, 64)) + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=NormalInitializer(std=0.02)) + + model = Model(X, layer(X)).initialize(seed=0) """ __props__ = ("mean", "std") @@ -130,6 +232,19 @@ def fans(shape: tuple[int, ...]) -> tuple[int, int]: Units feeding one output position. fan_out : int Output positions one input feeds. + + Examples + -------- + Report how many units feed into and out of one position of a parameter, which is what a fan-scaled draw + needs. A convolution kernel folds its receptive field into both counts, so the answer is not simply the + last two dimensions: + + .. code-block:: python + + from pytensor_ml.state import fans + + dense_fans = fans((64, 32)) + kernel_fans = fans((3, 5, 8, 16)) """ if len(shape) < 2: raise ValueError( @@ -152,6 +267,22 @@ class XavierUniformInitializer(Initializer): ---------- .. [1] Glorot, X. and Bengio, Y. (2010). Understanding the difficulty of training deep feedforward neural networks. Proceedings of AISTATS, 249-256. + + Examples + -------- + The default for weight matrices: bounds chosen so activations neither grow nor shrink as they pass + through the layer. Only the sum of the fans enters, so the layout of the parameter cannot skew it: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.state import XavierUniformInitializer + + X = Input("X", shape=(None, 64)) + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=XavierUniformInitializer()) + + model = Model(X, layer(X)).initialize(seed=0) """ def sample(self, shape: tuple[int, ...], dtype: str, rng: np.random.Generator) -> np.ndarray: @@ -170,6 +301,22 @@ class XavierNormalInitializer(Initializer): ---------- .. [1] Glorot, X. and Bengio, Y. (2010). Understanding the difficulty of training deep feedforward neural networks. Proceedings of AISTATS, 249-256. + + Examples + -------- + Xavier's variance drawn from a Gaussian rather than a bounded interval, so a few weights start + larger than any uniform draw would allow: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.state import XavierNormalInitializer + + X = Input("X", shape=(None, 64)) + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=XavierNormalInitializer()) + + model = Model(X, layer(X)).initialize(seed=0) """ def sample(self, shape: tuple[int, ...], dtype: str, rng: np.random.Generator) -> np.ndarray: @@ -196,6 +343,22 @@ class OrthogonalInitializer(Initializer): ---------- .. [1] Saxe, A. M., McClelland, J. L., and Ganguli, S. (2014). Exact solutions to the nonlinear dynamics of learning in deep linear neural networks. Proceedings of ICLR. + + Examples + -------- + Draws a matrix whose rows stay orthogonal, preserving the norm of whatever passes through it. That + is what keeps a recurrent layer's repeated multiplications from exploding or vanishing: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.model import Model + from pytensor_ml.state import OrthogonalInitializer + + X = Input("X", shape=(None, 64)) + layer = Linear("fc", n_in=64, n_out=32, weight_initializer=OrthogonalInitializer(gain=1.0)) + + model = Model(X, layer(X)).initialize(seed=0) """ __props__ = ("gain",) @@ -287,19 +450,28 @@ def initializer(sample_fn: Callable[..., np.ndarray]) -> type[Initializer]: Returns ------- - type of Initializer + initializer_class : type of Initializer A class to instantiate with the parameters, e.g. ``scaled_normal(std=0.02)``. Examples -------- + Decorate a sampling function to turn it into an initializer class a layer can take: + .. code-block:: python + import numpy as np + + from pytensor_ml.layers import Linear + from pytensor_ml.state import fans, initializer + + @initializer def he_normal(rng, shape): fan_in, _ = fans(shape) return rng.normal(0.0, np.sqrt(2.0 / fan_in), size=shape) - Linear("fc", 8, 8, weight_initializer=he_normal()) + + layer = Linear("fc", n_in=8, n_out=8, weight_initializer=he_normal()) """ parameters, defaults = _split_signature(sample_fn) @@ -356,6 +528,22 @@ class UnrecordedInitializer(Initializer): ---------- original : str Name of the initializer class the parameter was built with. + + Examples + -------- + What a parameter carries when its config named an initializer this build cannot resolve. It refuses to + draw, so a reloaded network reports the missing initializer rather than silently substituting one: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.params import trainable + from pytensor_ml.state import UnrecordedInitializer + + parameter = trainable( + np.zeros((4, 4)), "W", initializer=UnrecordedInitializer("my_package.custom_draw") + ) """ __props__ = ("original",) @@ -427,8 +615,25 @@ def initialize_params( Returns ------- - list of ndarray + values : list of ndarray Drawn values, matching the shapes and dtypes of ``params``. + + Examples + -------- + Draw fresh values for a list of parameters without touching them, which is what + :meth:`~pytensor_ml.model.Model.initialize` does before assigning. One seed reproduces the whole set: + + .. code-block:: python + + from pytensor_ml.layers import Input, Linear + from pytensor_ml.pytensorf import collect_trainable_params + from pytensor_ml.state import initialize_params + + X = Input("X", shape=(None, 64)) + activations = Linear("fc", n_in=64, n_out=32)(X) + + parameters = collect_trainable_params(activations) + values = initialize_params(parameters, rng=0) """ # Resolve once and share: a seed handed to each _sample_like call would repeat draws across parameters. rng = np.random.default_rng(rng) diff --git a/pytensor_ml/util.py b/pytensor_ml/util.py index eb75d27..b2efe86 100644 --- a/pytensor_ml/util.py +++ b/pytensor_ml/util.py @@ -23,6 +23,23 @@ class DataLoader: Dtype to cast ``X`` and ``y`` to. Defaults to ``floatX``. random_state : int or numpy Generator, optional Seed for the shuffling generator, for reproducible batch sequences. + + Examples + -------- + Call the loader once per training step; it reshuffles and wraps around on its own, so the loop + never has to track epoch boundaries: + + .. code-block:: python + + import numpy as np + + from pytensor_ml.util import DataLoader + + X = np.random.default_rng(0).normal(size=(500, 8)) + y = np.random.default_rng(1).normal(size=(500, 1)) + + loader = DataLoader(X, y, batch_size=32, random_state=0) + X_batch, y_batch = loader() """ def __init__(self, X, y, batch_size=64, dtype=None, random_state=None):