From 8f250a4797d8a312e71108ca0338245b0a5c36c3 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Tue, 16 Dec 2025 15:01:04 +0100
Subject: [PATCH 01/50] python port - first commit
---
.gitattributes | 2 +
.gitignore | 5 +
.vscode/settings.json | 4 +
README.md | 42 +-
pixi.lock | 1107 +++++++++++++++++++++++++++
pyproject.toml | 42 +
src/preface/__init__.py | 0
src/preface/lib/__init__.py | 0
src/preface/lib/functions.py | 0
src/preface/predict.py | 103 +++
src/preface/preface.py | 23 +
src/preface/train.py | 476 ++++++++++++
src/preface/utils/__init.py__ | 0
src/preface/utils/ffy.py | 2 +
src/preface/utils/npz_to_parquet.py | 85 ++
15 files changed, 1877 insertions(+), 14 deletions(-)
create mode 100644 .gitattributes
create mode 100644 .vscode/settings.json
create mode 100644 pixi.lock
create mode 100644 pyproject.toml
create mode 100644 src/preface/__init__.py
create mode 100644 src/preface/lib/__init__.py
create mode 100644 src/preface/lib/functions.py
create mode 100644 src/preface/predict.py
create mode 100644 src/preface/preface.py
create mode 100755 src/preface/train.py
create mode 100644 src/preface/utils/__init.py__
create mode 100644 src/preface/utils/ffy.py
create mode 100644 src/preface/utils/npz_to_parquet.py
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..997504b
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# SCM syntax highlighting & preventing 3-way merges
+pixi.lock merge=binary linguist-language=YAML linguist-generated=true -diff
diff --git a/.gitignore b/.gitignore
index 8ecd893..2dd0f89 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,7 @@
.DS_Store
.Rhistory
+data/
+*.egg-info
+# pixi environments
+.pixi/*
+!.pixi/config.toml
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..ba2a6c0
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,4 @@
+{
+ "python-envs.defaultEnvManager": "ms-python.python:system",
+ "python-envs.pythonProjects": []
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index d248c78..5b65978 100644
--- a/README.md
+++ b/README.md
@@ -30,11 +30,20 @@ For training, PREFACE requires a config file.
- The possible values for 'gender' are either 'M' (male) or 'F' (female), representing fetal gender. Twins/triplets/... can be included if they are all male or all female.
- The 'FF' column contains the response variable (the 'true' fetal fraction). One can use any method he/she believes performs best at quantifying the actual fetal fraction. PREFACE was benchmarked using the number of mapped Y-reads, referred to as FFY. As FFY is not informative for female fetuses, this measure is ignored for cases labeled with 'F', unless the `--femprop` flag is given (see below).
-## Model training
+## Installation & Setup
+
+PREFACE is a Python package that can be installed using `pip`.
```bash
+pip install .
+```
+
+This will install the `PREFACE` command-line tool.
-RScript PREFACE.R train --config path/to/config.txt --outdir path/to/dir/ [optional arguments]
+## Model training
+
+```bash
+PREFACE train --config path/to/config.txt --outdir path/to/dir/ [optional arguments]
```
Optional argument
| Function
@@ -49,8 +58,7 @@ RScript PREFACE.R train --config path/to/config.txt --outdir path/to/dir/ [optio
## Predicting
```bash
-
-RScript PREFACE.R predict --infile path/to/infile.bed --model path/to/model.RData [optional arguments]
+PREFACE predict --infile path/to/infile.bed --model path/to/model_directory [optional arguments]
```
Optional argument
| Function
@@ -67,19 +75,25 @@ RScript PREFACE.R predict --infile path/to/infile.bed --model path/to/model.RDat
- If you are not satisfied with the performance of your model or with the position of `--nfeat`, re-run with a different number of features.
- Note that the final model will probably be a bit more accurate than what is claimed by the performance statistics. This is because PREFACE uses a cross-validation strategy where 10% of the (male) samples are excluded from training, after which these 10% serve as validation cases. This process is repeated 10 times. Therefore, the final performance measurements are based on models trained with only 90% of the (male) fetuses, yet the resulting model is trained with all provided cases.
-# Required R packages
+# Utilities
+
+## NPZ to Parquet Converter
-- doParallel (v1.0.14)
-- foreach (v1.4.4)
-- neuralnet (v1.44.2)
-- glmnet (v2.0-16)
-- data.table (v1.11.8)
-- MASS (v7.3-49)
-- irlba (v2.3.3)
+This script converts NumPy `.npz` files into one or more Parquet files, facilitating easier exploration and analysis of the stored numerical data using tools like Pandas. Each array within an `.npz` file will be converted to a separate Parquet file.
-Other versions are of course expected to work equally well. To install within R use:
+### Usage
```bash
+npz-to-parquet [ ...] [-o ]
+```
+
+- ` [ ...]`: One or more paths to the input `.npz` files.
+- `-o, --output-dir`: (Optional) Directory to save the output Parquet files. Defaults to the current directory (`.`).
-install.packages(c('data.table', 'glmnet', 'neuralnet', 'foreach', 'doParallel', 'MASS', 'irlba'))
+### Example
+
+To convert `data.npz` and `features.npz` and save the output Parquet files in a directory named `parquet_output`:
+
+```bash
+npz-to-parquet data.npz features.npz -o parquet_output
```
diff --git a/pixi.lock b/pixi.lock
new file mode 100644
index 0000000..8d0a7b5
--- /dev/null
+++ b/pixi.lock
@@ -0,0 +1,1107 @@
+version: 6
+environments:
+ default:
+ channels:
+ - url: https://conda.anaconda.org/conda-forge/
+ indexes:
+ - https://pypi.org/simple
+ options:
+ pypi-prerelease-mode: if-necessary-or-explicit
+ packages:
+ osx-arm64:
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_100_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ - pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: ./
+packages:
+- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ name: absl-py
+ version: 2.3.1
+ sha256: eeecf07f0c2a93ace0772c92e596ace6d3d3996c042b2128459aaae2a76de11d
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
+ name: astunparse
+ version: 1.6.3
+ sha256: c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8
+ requires_dist:
+ - wheel>=0.23.0,<1.0
+ - six>=1.6.1,<2.0
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda
+ sha256: b456200636bd5fecb2bec63f7e0985ad2097cf1b83d60ce0b6968dffa6d02aa1
+ md5: 58fd217444c2a5701a44244faf518206
+ depends:
+ - __osx >=11.0
+ license: bzip2-1.0.6
+ license_family: BSD
+ purls: []
+ size: 125061
+ timestamp: 1757437486465
+- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
+ sha256: b986ba796d42c9d3265602bc038f6f5264095702dd546c14bc684e60c385e773
+ md5: f0991f0f84902f6b6009b4d2350a83aa
+ depends:
+ - __unix
+ license: ISC
+ purls: []
+ size: 152432
+ timestamp: 1762967197890
+- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
+ name: certifi
+ version: 2025.11.12
+ sha256: 97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
+ name: charset-normalizer
+ version: 3.4.4
+ sha256: e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ name: click
+ version: 8.3.1
+ sha256: 981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6
+ requires_dist:
+ - colorama ; sys_platform == 'win32'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
+ name: contourpy
+ version: 1.3.3
+ sha256: d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1
+ requires_dist:
+ - numpy>=1.25
+ - furo ; extra == 'docs'
+ - sphinx>=7.2 ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - bokeh ; extra == 'bokeh'
+ - selenium ; extra == 'bokeh'
+ - contourpy[bokeh,docs] ; extra == 'mypy'
+ - bokeh ; extra == 'mypy'
+ - docutils-stubs ; extra == 'mypy'
+ - mypy==1.17.0 ; extra == 'mypy'
+ - types-pillow ; extra == 'mypy'
+ - contourpy[test-no-images] ; extra == 'test'
+ - matplotlib ; extra == 'test'
+ - pillow ; extra == 'test'
+ - pytest ; extra == 'test-no-images'
+ - pytest-cov ; extra == 'test-no-images'
+ - pytest-rerunfailures ; extra == 'test-no-images'
+ - pytest-xdist ; extra == 'test-no-images'
+ - wurlitzer ; extra == 'test-no-images'
+ requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
+ name: cycler
+ version: 0.12.1
+ sha256: 85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30
+ requires_dist:
+ - ipython ; extra == 'docs'
+ - matplotlib ; extra == 'docs'
+ - numpydoc ; extra == 'docs'
+ - sphinx ; extra == 'docs'
+ - pytest ; extra == 'tests'
+ - pytest-cov ; extra == 'tests'
+ - pytest-xdist ; extra == 'tests'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+ name: flatbuffers
+ version: 25.9.23
+ sha256: 255538574d6cb6d0a79a17ec8bc0d30985913b87513a01cce8bcdb6b4c44d0e2
+- pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
+ name: fonttools
+ version: 4.61.1
+ sha256: 8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c
+ requires_dist:
+ - lxml>=4.0 ; extra == 'lxml'
+ - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
+ - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff'
+ - zopfli>=0.1.4 ; extra == 'woff'
+ - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode'
+ - lz4>=1.7.4.2 ; extra == 'graphite'
+ - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable'
+ - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable'
+ - pycairo ; extra == 'interpolatable'
+ - matplotlib ; extra == 'plot'
+ - sympy ; extra == 'symfont'
+ - xattr ; sys_platform == 'darwin' and extra == 'type1'
+ - skia-pathops>=0.5.0 ; extra == 'pathops'
+ - uharfbuzz>=0.45.0 ; extra == 'repacker'
+ - lxml>=4.0 ; extra == 'all'
+ - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all'
+ - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all'
+ - zopfli>=0.1.4 ; extra == 'all'
+ - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all'
+ - lz4>=1.7.4.2 ; extra == 'all'
+ - scipy ; platform_python_implementation != 'PyPy' and extra == 'all'
+ - munkres ; platform_python_implementation == 'PyPy' and extra == 'all'
+ - pycairo ; extra == 'all'
+ - matplotlib ; extra == 'all'
+ - sympy ; extra == 'all'
+ - xattr ; sys_platform == 'darwin' and extra == 'all'
+ - skia-pathops>=0.5.0 ; extra == 'all'
+ - uharfbuzz>=0.45.0 ; extra == 'all'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
+ name: gast
+ version: 0.7.0
+ sha256: 99cbf1365633a74099f69c59bd650476b96baa5ef196fec88032b00b31ba36f7
+ requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*'
+- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
+ name: google-pasta
+ version: 0.2.0
+ sha256: b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed
+ requires_dist:
+ - six
+- pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
+ name: grpcio
+ version: 1.76.0
+ sha256: 45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468
+ requires_dist:
+ - typing-extensions~=4.12
+ - grpcio-tools>=1.76.0 ; extra == 'protobuf'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
+ name: h5py
+ version: 3.15.1
+ sha256: ab2219dbc6fcdb6932f76b548e2b16f34a1f52b7666e998157a4dfc02e2c4123
+ requires_dist:
+ - numpy>=1.21.2
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ name: idna
+ version: '3.11'
+ sha256: 771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea
+ requires_dist:
+ - ruff>=0.6.2 ; extra == 'all'
+ - mypy>=1.11.2 ; extra == 'all'
+ - pytest>=8.3.2 ; extra == 'all'
+ - flake8>=7.1.1 ; extra == 'all'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ name: joblib
+ version: 1.5.3
+ sha256: 5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+ name: keras
+ version: 3.12.0
+ sha256: 02b69e007d5df8042286c3bcc2a888539e3e487590ffb08f6be1b4354df50aa8
+ requires_dist:
+ - absl-py
+ - numpy
+ - rich
+ - namex
+ - h5py
+ - optree
+ - ml-dtypes
+ - packaging
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
+ name: kiwisolver
+ version: 1.4.9
+ sha256: 1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
+ name: libclang
+ version: 18.1.1
+ sha256: 0b2e143f0fac830156feb56f9231ff8338c20aecfe72b4ffe96f19e5a1dbb69a
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
+ sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98
+ md5: b79875dbb5b1db9a4a22a4520f918e1a
+ depends:
+ - __osx >=11.0
+ constrains:
+ - expat 2.7.3.*
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 67800
+ timestamp: 1763549994166
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
+ sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f
+ md5: 411ff7cd5d1472bba0f55c0faf04453b
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 40251
+ timestamp: 1760295839166
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda
+ sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285
+ md5: d6df911d4564d77c4374b02552cb17d1
+ depends:
+ - __osx >=11.0
+ constrains:
+ - xz 5.8.1.*
+ license: 0BSD
+ purls: []
+ size: 92286
+ timestamp: 1749230283517
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda
+ sha256: 0a1875fc1642324ebd6c4ac864604f3f18f57fbcf558a8264f6ced028a3c75b2
+ md5: 85ccccb47823dd9f7a99d2c7f530342f
+ depends:
+ - __osx >=11.0
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 71829
+ timestamp: 1748393749336
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda
+ sha256: a46b167447e2a9e38586320c30b29e3b68b6f7e6b873c18d6b1aa2efd2626917
+ md5: 67e50e5bd4e5e2310d66b88c4da50096
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.1,<2.0a0
+ license: blessing
+ purls: []
+ size: 906292
+ timestamp: 1764359907797
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
+ sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b
+ md5: 369964e85dc26bfe78f41399b366c435
+ depends:
+ - __osx >=11.0
+ constrains:
+ - zlib 1.3.1 *_2
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 46438
+ timestamp: 1727963202283
+- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
+ name: markdown
+ version: '3.10'
+ sha256: b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c
+ requires_dist:
+ - coverage ; extra == 'testing'
+ - pyyaml ; extra == 'testing'
+ - mkdocs>=1.6 ; extra == 'docs'
+ - mkdocs-nature>=0.6 ; extra == 'docs'
+ - mdx-gh-links>=0.2 ; extra == 'docs'
+ - mkdocstrings[python] ; extra == 'docs'
+ - mkdocs-gen-files ; extra == 'docs'
+ - mkdocs-section-index ; extra == 'docs'
+ - mkdocs-literate-nav ; extra == 'docs'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
+ name: markdown-it-py
+ version: 4.0.0
+ sha256: 87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147
+ requires_dist:
+ - mdurl~=0.1
+ - psutil ; extra == 'benchmarking'
+ - pytest ; extra == 'benchmarking'
+ - pytest-benchmark ; extra == 'benchmarking'
+ - commonmark~=0.9 ; extra == 'compare'
+ - markdown~=3.4 ; extra == 'compare'
+ - mistletoe~=1.0 ; extra == 'compare'
+ - mistune~=3.0 ; extra == 'compare'
+ - panflute~=2.3 ; extra == 'compare'
+ - markdown-it-pyrs ; extra == 'compare'
+ - linkify-it-py>=1,<3 ; extra == 'linkify'
+ - mdit-py-plugins>=0.5.0 ; extra == 'plugins'
+ - gprof2dot ; extra == 'profiling'
+ - mdit-py-plugins>=0.5.0 ; extra == 'rtd'
+ - myst-parser ; extra == 'rtd'
+ - pyyaml ; extra == 'rtd'
+ - sphinx ; extra == 'rtd'
+ - sphinx-copybutton ; extra == 'rtd'
+ - sphinx-design ; extra == 'rtd'
+ - sphinx-book-theme~=1.0 ; extra == 'rtd'
+ - jupyter-sphinx ; extra == 'rtd'
+ - ipykernel ; extra == 'rtd'
+ - coverage ; extra == 'testing'
+ - pytest ; extra == 'testing'
+ - pytest-cov ; extra == 'testing'
+ - pytest-regressions ; extra == 'testing'
+ - requests ; extra == 'testing'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
+ name: markupsafe
+ version: 3.0.3
+ sha256: 116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
+ name: matplotlib
+ version: 3.10.8
+ sha256: 56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1
+ requires_dist:
+ - contourpy>=1.0.1
+ - cycler>=0.10
+ - fonttools>=4.22.0
+ - kiwisolver>=1.3.1
+ - numpy>=1.23
+ - packaging>=20.0
+ - pillow>=8
+ - pyparsing>=3
+ - python-dateutil>=2.7
+ - meson-python>=0.13.1,<0.17.0 ; extra == 'dev'
+ - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev'
+ - setuptools-scm>=7 ; extra == 'dev'
+ - setuptools>=64 ; extra == 'dev'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
+ name: mdurl
+ version: 0.1.2
+ sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
+ name: ml-dtypes
+ version: 0.5.4
+ sha256: 8c760d85a2f82e2bed75867079188c9d18dae2ee77c25a54d60e9cc79be1bc48
+ requires_dist:
+ - numpy>=1.21
+ - numpy>=1.21.2 ; python_full_version >= '3.10'
+ - numpy>=1.23.3 ; python_full_version >= '3.11'
+ - numpy>=1.26.0 ; python_full_version >= '3.12'
+ - numpy>=2.1.0 ; python_full_version >= '3.13'
+ - absl-py ; extra == 'dev'
+ - pytest ; extra == 'dev'
+ - pytest-xdist ; extra == 'dev'
+ - pylint>=2.6.0 ; extra == 'dev'
+ - pyink ; extra == 'dev'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ name: namex
+ version: 0.1.0
+ sha256: e2012a474502f1e2251267062aae3114611f07df4224b6e06334c57b0f2ce87c
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
+ sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733
+ md5: 068d497125e4bf8a66bf707254fff5ae
+ depends:
+ - __osx >=11.0
+ license: X11 AND BSD-3-Clause
+ purls: []
+ size: 797030
+ timestamp: 1738196177597
+- pypi: https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl
+ name: numpy
+ version: 2.3.5
+ sha256: aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188
+ requires_python: '>=3.11'
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
+ sha256: ebe93dafcc09e099782fe3907485d4e1671296bc14f8c383cb6f3dfebb773988
+ md5: b34dc4172653c13dcf453862f251af2b
+ depends:
+ - __osx >=11.0
+ - ca-certificates
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 3108371
+ timestamp: 1762839712322
+- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
+ name: opt-einsum
+ version: 3.4.0
+ sha256: 69bb92469f86a1565195ece4ac0323943e83477171b91d24c35afe028a90d7cd
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
+ name: optree
+ version: 0.18.0
+ sha256: fa8e3878a1857761d64f08a23b32140d29754a53f85f7c87186ced2b5b1b49cb
+ requires_dist:
+ - typing-extensions>=4.6.0
+ - typing-extensions>=4.12.0 ; python_full_version >= '3.13'
+ - jax ; extra == 'jax'
+ - numpy ; extra == 'numpy'
+ - torch ; extra == 'torch'
+ - ruff ; extra == 'lint'
+ - pylint[spelling] ; extra == 'lint'
+ - mypy ; extra == 'lint'
+ - doc8 ; extra == 'lint'
+ - pyenchant ; extra == 'lint'
+ - xdoctest ; extra == 'lint'
+ - cpplint ; extra == 'lint'
+ - pre-commit ; extra == 'lint'
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - covdefaults ; extra == 'test'
+ - rich ; extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'linux' and extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'darwin' and extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'win32' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'linux' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'darwin' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'win32' and extra == 'test'
+ - sphinx ; extra == 'docs'
+ - sphinx-autoapi ; extra == 'docs'
+ - sphinx-autobuild ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - sphinx-rtd-theme ; extra == 'docs'
+ - sphinxcontrib-bibtex ; extra == 'docs'
+ - sphinx-autodoc-typehints ; extra == 'docs'
+ - docutils ; extra == 'docs'
+ - jax[cpu] ; extra == 'docs'
+ - numpy ; extra == 'docs'
+ - torch ; extra == 'docs'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
+ name: packaging
+ version: '25.0'
+ sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
+ name: pandas
+ version: 2.3.3
+ sha256: bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8
+ requires_dist:
+ - numpy>=1.22.4 ; python_full_version < '3.11'
+ - numpy>=1.23.2 ; python_full_version == '3.11.*'
+ - numpy>=1.26.0 ; python_full_version >= '3.12'
+ - python-dateutil>=2.8.2
+ - pytz>=2020.1
+ - tzdata>=2022.7
+ - hypothesis>=6.46.1 ; extra == 'test'
+ - pytest>=7.3.2 ; extra == 'test'
+ - pytest-xdist>=2.2.0 ; extra == 'test'
+ - pyarrow>=10.0.1 ; extra == 'pyarrow'
+ - bottleneck>=1.3.6 ; extra == 'performance'
+ - numba>=0.56.4 ; extra == 'performance'
+ - numexpr>=2.8.4 ; extra == 'performance'
+ - scipy>=1.10.0 ; extra == 'computation'
+ - xarray>=2022.12.0 ; extra == 'computation'
+ - fsspec>=2022.11.0 ; extra == 'fss'
+ - s3fs>=2022.11.0 ; extra == 'aws'
+ - gcsfs>=2022.11.0 ; extra == 'gcp'
+ - pandas-gbq>=0.19.0 ; extra == 'gcp'
+ - odfpy>=1.4.1 ; extra == 'excel'
+ - openpyxl>=3.1.0 ; extra == 'excel'
+ - python-calamine>=0.1.7 ; extra == 'excel'
+ - pyxlsb>=1.0.10 ; extra == 'excel'
+ - xlrd>=2.0.1 ; extra == 'excel'
+ - xlsxwriter>=3.0.5 ; extra == 'excel'
+ - pyarrow>=10.0.1 ; extra == 'parquet'
+ - pyarrow>=10.0.1 ; extra == 'feather'
+ - tables>=3.8.0 ; extra == 'hdf5'
+ - pyreadstat>=1.2.0 ; extra == 'spss'
+ - sqlalchemy>=2.0.0 ; extra == 'postgresql'
+ - psycopg2>=2.9.6 ; extra == 'postgresql'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql'
+ - sqlalchemy>=2.0.0 ; extra == 'mysql'
+ - pymysql>=1.0.2 ; extra == 'mysql'
+ - sqlalchemy>=2.0.0 ; extra == 'sql-other'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other'
+ - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other'
+ - beautifulsoup4>=4.11.2 ; extra == 'html'
+ - html5lib>=1.1 ; extra == 'html'
+ - lxml>=4.9.2 ; extra == 'html'
+ - lxml>=4.9.2 ; extra == 'xml'
+ - matplotlib>=3.6.3 ; extra == 'plot'
+ - jinja2>=3.1.2 ; extra == 'output-formatting'
+ - tabulate>=0.9.0 ; extra == 'output-formatting'
+ - pyqt5>=5.15.9 ; extra == 'clipboard'
+ - qtpy>=2.3.0 ; extra == 'clipboard'
+ - zstandard>=0.19.0 ; extra == 'compression'
+ - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'all'
+ - adbc-driver-sqlite>=0.8.0 ; extra == 'all'
+ - beautifulsoup4>=4.11.2 ; extra == 'all'
+ - bottleneck>=1.3.6 ; extra == 'all'
+ - dataframe-api-compat>=0.1.7 ; extra == 'all'
+ - fastparquet>=2022.12.0 ; extra == 'all'
+ - fsspec>=2022.11.0 ; extra == 'all'
+ - gcsfs>=2022.11.0 ; extra == 'all'
+ - html5lib>=1.1 ; extra == 'all'
+ - hypothesis>=6.46.1 ; extra == 'all'
+ - jinja2>=3.1.2 ; extra == 'all'
+ - lxml>=4.9.2 ; extra == 'all'
+ - matplotlib>=3.6.3 ; extra == 'all'
+ - numba>=0.56.4 ; extra == 'all'
+ - numexpr>=2.8.4 ; extra == 'all'
+ - odfpy>=1.4.1 ; extra == 'all'
+ - openpyxl>=3.1.0 ; extra == 'all'
+ - pandas-gbq>=0.19.0 ; extra == 'all'
+ - psycopg2>=2.9.6 ; extra == 'all'
+ - pyarrow>=10.0.1 ; extra == 'all'
+ - pymysql>=1.0.2 ; extra == 'all'
+ - pyqt5>=5.15.9 ; extra == 'all'
+ - pyreadstat>=1.2.0 ; extra == 'all'
+ - pytest>=7.3.2 ; extra == 'all'
+ - pytest-xdist>=2.2.0 ; extra == 'all'
+ - python-calamine>=0.1.7 ; extra == 'all'
+ - pyxlsb>=1.0.10 ; extra == 'all'
+ - qtpy>=2.3.0 ; extra == 'all'
+ - scipy>=1.10.0 ; extra == 'all'
+ - s3fs>=2022.11.0 ; extra == 'all'
+ - sqlalchemy>=2.0.0 ; extra == 'all'
+ - tables>=3.8.0 ; extra == 'all'
+ - tabulate>=0.9.0 ; extra == 'all'
+ - xarray>=2022.12.0 ; extra == 'all'
+ - xlrd>=2.0.1 ; extra == 'all'
+ - xlsxwriter>=3.0.5 ; extra == 'all'
+ - zstandard>=0.19.0 ; extra == 'all'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ name: patsy
+ version: 1.0.2
+ sha256: 37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a
+ requires_dist:
+ - numpy>=1.4
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - scipy ; extra == 'test'
+ requires_python: '>=3.6'
+- pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
+ name: pillow
+ version: 12.0.0
+ sha256: 5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b
+ requires_dist:
+ - furo ; extra == 'docs'
+ - olefile ; extra == 'docs'
+ - sphinx>=8.2 ; extra == 'docs'
+ - sphinx-autobuild ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - sphinx-inline-tabs ; extra == 'docs'
+ - sphinxext-opengraph ; extra == 'docs'
+ - olefile ; extra == 'fpx'
+ - olefile ; extra == 'mic'
+ - arro3-compute ; extra == 'test-arrow'
+ - arro3-core ; extra == 'test-arrow'
+ - nanoarrow ; extra == 'test-arrow'
+ - pyarrow ; extra == 'test-arrow'
+ - check-manifest ; extra == 'tests'
+ - coverage>=7.4.2 ; extra == 'tests'
+ - defusedxml ; extra == 'tests'
+ - markdown2 ; extra == 'tests'
+ - olefile ; extra == 'tests'
+ - packaging ; extra == 'tests'
+ - pyroma>=5 ; extra == 'tests'
+ - pytest ; extra == 'tests'
+ - pytest-cov ; extra == 'tests'
+ - pytest-timeout ; extra == 'tests'
+ - pytest-xdist ; extra == 'tests'
+ - trove-classifiers>=2024.10.12 ; extra == 'tests'
+ - defusedxml ; extra == 'xmp'
+ requires_python: '>=3.10'
+- pypi: ./
+ name: preface
+ version: 1.0.0.dev0
+ sha256: c237680684b4cf004969398069852d16b5c3f766197c0b9e3e7b05223ff56beb
+ requires_dist:
+ - pandas>=2.3.3,<3
+ - numpy>=2.3.5,<3
+ - scikit-learn>=1.8.0,<2
+ - tensorflow>=2.20.0,<3
+ - matplotlib>=3.10.8,<4
+ - joblib>=1.5.3,<2
+ - statsmodels>=0.14.6,<0.15
+ - typer>=0.20.0,<0.21
+ requires_python: '>=3.11,<3.14'
+ editable: true
+- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
+ name: protobuf
+ version: 6.33.2
+ sha256: d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
+ name: pygments
+ version: 2.19.2
+ sha256: 86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
+ requires_dist:
+ - colorama>=0.4.6 ; extra == 'windows-terminal'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+ name: pyparsing
+ version: 3.2.5
+ sha256: e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e
+ requires_dist:
+ - railroad-diagrams ; extra == 'diagrams'
+ - jinja2 ; extra == 'diagrams'
+ requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_100_cp313.conda
+ build_number: 100
+ sha256: c476f4e9b6d97c46b496b442878924868a54e5727251549ebfc82027aa52af68
+ md5: 18a8c69608151098a8fb75eea64cc266
+ depends:
+ - __osx >=11.0
+ - bzip2 >=1.0.8,<2.0a0
+ - libexpat >=2.7.3,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libmpdec >=4.0.0,<5.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - ncurses >=6.5,<7.0a0
+ - openssl >=3.5.4,<4.0a0
+ - python_abi 3.13.* *_cp313
+ - readline >=8.2,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ license: Python-2.0
+ purls: []
+ size: 12920650
+ timestamp: 1765020887340
+ python_site_packages_path: lib/python3.13/site-packages
+- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
+ name: python-dateutil
+ version: 2.9.0.post0
+ sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
+ requires_dist:
+ - six>=1.5
+ requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
+- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
+ build_number: 8
+ sha256: 210bffe7b121e651419cb196a2a63687b087497595c9be9d20ebe97dd06060a7
+ md5: 94305520c52a4aa3f6c2b1ff6008d9f8
+ constrains:
+ - python 3.13.* *_cp313
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 7002
+ timestamp: 1752805902938
+- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
+ name: pytz
+ version: '2025.2'
+ sha256: 5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
+ sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477
+ md5: f8381319127120ce51e081dce4865cf4
+ depends:
+ - __osx >=11.0
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ purls: []
+ size: 313930
+ timestamp: 1765813902568
+- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ name: requests
+ version: 2.32.5
+ sha256: 2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6
+ requires_dist:
+ - charset-normalizer>=2,<4
+ - idna>=2.5,<4
+ - urllib3>=1.21.1,<3
+ - certifi>=2017.4.17
+ - pysocks>=1.5.6,!=1.5.7 ; extra == 'socks'
+ - chardet>=3.0.2,<6 ; extra == 'use-chardet-on-py3'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
+ name: rich
+ version: 14.2.0
+ sha256: 76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd
+ requires_dist:
+ - ipywidgets>=7.5.1,<9 ; extra == 'jupyter'
+ - markdown-it-py>=2.2.0
+ - pygments>=2.13.0,<3.0.0
+ requires_python: '>=3.8.0'
+- pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
+ name: scikit-learn
+ version: 1.8.0
+ sha256: edec98c5e7c128328124a029bceb09eda2d526997780fef8d65e9a69eead963e
+ requires_dist:
+ - numpy>=1.24.1
+ - scipy>=1.10.0
+ - joblib>=1.3.0
+ - threadpoolctl>=3.2.0
+ - numpy>=1.24.1 ; extra == 'build'
+ - scipy>=1.10.0 ; extra == 'build'
+ - cython>=3.1.2 ; extra == 'build'
+ - meson-python>=0.17.1 ; extra == 'build'
+ - numpy>=1.24.1 ; extra == 'install'
+ - scipy>=1.10.0 ; extra == 'install'
+ - joblib>=1.3.0 ; extra == 'install'
+ - threadpoolctl>=3.2.0 ; extra == 'install'
+ - matplotlib>=3.6.1 ; extra == 'benchmark'
+ - pandas>=1.5.0 ; extra == 'benchmark'
+ - memory-profiler>=0.57.0 ; extra == 'benchmark'
+ - matplotlib>=3.6.1 ; extra == 'docs'
+ - scikit-image>=0.22.0 ; extra == 'docs'
+ - pandas>=1.5.0 ; extra == 'docs'
+ - seaborn>=0.13.0 ; extra == 'docs'
+ - memory-profiler>=0.57.0 ; extra == 'docs'
+ - sphinx>=7.3.7 ; extra == 'docs'
+ - sphinx-copybutton>=0.5.2 ; extra == 'docs'
+ - sphinx-gallery>=0.17.1 ; extra == 'docs'
+ - numpydoc>=1.2.0 ; extra == 'docs'
+ - pillow>=10.1.0 ; extra == 'docs'
+ - pooch>=1.8.0 ; extra == 'docs'
+ - sphinx-prompt>=1.4.0 ; extra == 'docs'
+ - sphinxext-opengraph>=0.9.1 ; extra == 'docs'
+ - plotly>=5.18.0 ; extra == 'docs'
+ - polars>=0.20.30 ; extra == 'docs'
+ - sphinx-design>=0.6.0 ; extra == 'docs'
+ - sphinxcontrib-sass>=0.3.4 ; extra == 'docs'
+ - pydata-sphinx-theme>=0.15.3 ; extra == 'docs'
+ - sphinx-remove-toctrees>=1.0.0.post1 ; extra == 'docs'
+ - towncrier>=24.8.0 ; extra == 'docs'
+ - matplotlib>=3.6.1 ; extra == 'examples'
+ - scikit-image>=0.22.0 ; extra == 'examples'
+ - pandas>=1.5.0 ; extra == 'examples'
+ - seaborn>=0.13.0 ; extra == 'examples'
+ - pooch>=1.8.0 ; extra == 'examples'
+ - plotly>=5.18.0 ; extra == 'examples'
+ - matplotlib>=3.6.1 ; extra == 'tests'
+ - pandas>=1.5.0 ; extra == 'tests'
+ - pytest>=7.1.2 ; extra == 'tests'
+ - pytest-cov>=2.9.0 ; extra == 'tests'
+ - ruff>=0.11.7 ; extra == 'tests'
+ - mypy>=1.15 ; extra == 'tests'
+ - pyamg>=5.0.0 ; extra == 'tests'
+ - polars>=0.20.30 ; extra == 'tests'
+ - pyarrow>=12.0.0 ; extra == 'tests'
+ - numpydoc>=1.2.0 ; extra == 'tests'
+ - pooch>=1.8.0 ; extra == 'tests'
+ - conda-lock==3.0.1 ; extra == 'maintenance'
+ requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl
+ name: scipy
+ version: 1.16.3
+ sha256: 16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d
+ requires_dist:
+ - numpy>=1.25.2,<2.6
+ - 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'
+ - 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'
+ - mypy==1.10.0 ; extra == 'dev'
+ - typing-extensions ; extra == 'dev'
+ - types-psutil ; extra == 'dev'
+ - pycodestyle ; extra == 'dev'
+ - ruff>=0.0.292 ; extra == 'dev'
+ - cython-lint>=0.12.2 ; extra == 'dev'
+ - rich-click ; extra == 'dev'
+ - doit>=0.36.0 ; extra == 'dev'
+ - pydevtool ; extra == 'dev'
+ requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
+ name: setuptools
+ version: 80.9.0
+ sha256: 062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922
+ 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'
+ - platformdirs>=4.2.2 ; extra == 'core'
+ - jaraco-functools>=4 ; extra == 'core'
+ - more-itertools ; extra == 'core'
+ - pytest-checkdocs>=2.4 ; extra == 'check'
+ - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check'
+ - ruff>=0.8.0 ; sys_platform != 'cygwin' and extra == 'check'
+ - pytest-cov ; extra == 'cover'
+ - pytest-enabler>=2.2 ; extra == 'enabler'
+ - pytest-mypy ; extra == 'type'
+ - mypy==1.14.* ; 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.9'
+- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
+ name: shellingham
+ version: 1.5.4
+ sha256: 7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ name: six
+ version: 1.17.0
+ sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
+ requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
+ name: statsmodels
+ version: 0.14.6
+ sha256: aa60d82e29fcd0a736e86feb63a11d2380322d77a9369a54be8b0965a3985f71
+ requires_dist:
+ - numpy>=1.22.3,<3
+ - scipy>=1.8,!=1.9.2
+ - pandas>=1.4,!=2.1.0
+ - patsy>=0.5.6
+ - packaging>=21.3
+ - cython>=3.0.10 ; extra == 'build'
+ - cython>=3.0.10 ; extra == 'develop'
+ - cython>=3.0.10,<4 ; extra == 'develop'
+ - setuptools-scm[toml]~=8.0 ; extra == 'develop'
+ - matplotlib>=3 ; extra == 'develop'
+ - colorama ; extra == 'develop'
+ - joblib ; extra == 'develop'
+ - jinja2 ; extra == 'develop'
+ - pytest>=7.3.0,<8 ; extra == 'develop'
+ - pytest-randomly ; extra == 'develop'
+ - pytest-xdist ; extra == 'develop'
+ - pytest-cov ; extra == 'develop'
+ - pywinpty ; os_name == 'nt' and extra == 'develop'
+ - flake8 ; extra == 'develop'
+ - isort ; extra == 'develop'
+ - sphinx ; extra == 'docs'
+ - nbconvert ; extra == 'docs'
+ - jupyter-client ; extra == 'docs'
+ - ipykernel ; extra == 'docs'
+ - matplotlib ; extra == 'docs'
+ - nbformat ; extra == 'docs'
+ - numpydoc ; extra == 'docs'
+ - pandas-datareader ; extra == 'docs'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
+ name: tensorboard
+ version: 2.20.0
+ sha256: 9dc9f978cb84c0723acf9a345d96c184f0293d18f166bb8d59ee098e6cfaaba6
+ requires_dist:
+ - absl-py>=0.4
+ - grpcio>=1.48.2
+ - markdown>=2.6.8
+ - numpy>=1.12.0
+ - packaging
+ - pillow
+ - protobuf>=3.19.6,!=4.24.0
+ - setuptools>=41.0.0
+ - tensorboard-data-server>=0.7.0,<0.8.0
+ - werkzeug>=1.0.1
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
+ name: tensorboard-data-server
+ version: 0.7.2
+ sha256: 7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
+ name: tensorflow
+ version: 2.20.0
+ sha256: 197f0b613b38c0da5c6a12a8295ad4a05c78b853835dae8e0f9dfae3ce9ce8a5
+ requires_dist:
+ - absl-py>=1.0.0
+ - astunparse>=1.6.0
+ - flatbuffers>=24.3.25
+ - gast>=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
+ - google-pasta>=0.1.1
+ - libclang>=13.0.0
+ - opt-einsum>=2.3.2
+ - packaging
+ - protobuf>=5.28.0
+ - requests>=2.21.0,<3
+ - setuptools
+ - six>=1.12.0
+ - termcolor>=1.1.0
+ - typing-extensions>=3.6.6
+ - wrapt>=1.11.0
+ - grpcio>=1.24.3,<2.0
+ - tensorboard~=2.20.0
+ - keras>=3.10.0
+ - numpy>=1.26.0
+ - h5py>=3.11.0
+ - ml-dtypes>=0.5.1,<1.0.0
+ - nvidia-cublas-cu12>=12.5.3.2,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-cupti-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-nvcc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-nvrtc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-runtime-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cudnn-cu12>=9.3.0.75,<10.0 ; extra == 'and-cuda'
+ - nvidia-cufft-cu12>=11.2.3.61,<12.0 ; extra == 'and-cuda'
+ - nvidia-curand-cu12>=10.3.6.82,<11.0 ; extra == 'and-cuda'
+ - nvidia-cusolver-cu12>=11.6.3.83,<12.0 ; extra == 'and-cuda'
+ - nvidia-cusparse-cu12>=12.5.1.3,<13.0 ; extra == 'and-cuda'
+ - nvidia-nccl-cu12>=2.25.1,<3.0 ; extra == 'and-cuda'
+ - nvidia-nvjitlink-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
+ - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ name: termcolor
+ version: 3.2.0
+ sha256: a10343879eba4da819353c55cb8049b0933890c2ebf9ad5d3ecd2bb32ea96ea6
+ requires_dist:
+ - pytest ; extra == 'tests'
+ - pytest-cov ; extra == 'tests'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ name: threadpoolctl
+ version: 3.6.0
+ sha256: 43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb
+ requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
+ sha256: ad0c67cb03c163a109820dc9ecf77faf6ec7150e942d1e8bb13e5d39dc058ab7
+ md5: a73d54a5abba6543cb2f0af1bfbd6851
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.1,<2.0a0
+ license: TCL
+ license_family: BSD
+ purls: []
+ size: 3125484
+ timestamp: 1763055028377
+- pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+ name: typer
+ version: 0.20.0
+ sha256: 5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a
+ requires_dist:
+ - click>=8.0.0
+ - typing-extensions>=3.7.4.3
+ - shellingham>=1.3.0
+ - rich>=10.11.0
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
+ name: typing-extensions
+ version: 4.15.0
+ sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
+ name: tzdata
+ version: '2025.3'
+ sha256: 06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1
+ requires_python: '>=2'
+- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ sha256: 50fad5db6734d1bb73df1cf5db73215e326413d4b2137933f70708aa1840e25b
+ md5: 338201218b54cadff2e774ac27733990
+ license: LicenseRef-Public-Domain
+ purls: []
+ size: 119204
+ timestamp: 1765745742795
+- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
+ name: urllib3
+ version: 2.6.2
+ sha256: ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd
+ requires_dist:
+ - brotli>=1.2.0 ; platform_python_implementation == 'CPython' and extra == 'brotli'
+ - brotlicffi>=1.2.0.0 ; platform_python_implementation != 'CPython' and extra == 'brotli'
+ - h2>=4,<5 ; extra == 'h2'
+ - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks'
+ - backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
+ name: werkzeug
+ version: 3.1.4
+ sha256: 2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905
+ requires_dist:
+ - markupsafe>=2.1.1
+ - watchdog>=2.3 ; extra == 'watchdog'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
+ name: wheel
+ version: 0.45.1
+ sha256: 708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248
+ requires_dist:
+ - pytest>=6.0.0 ; extra == 'test'
+ - setuptools>=65 ; extra == 'test'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
+ name: wrapt
+ version: 2.0.1
+ sha256: eb7cffe572ad0a141a7886a1d2efa5bef0bf7fe021deeea76b3ab334d2c38218
+ requires_dist:
+ - pytest ; extra == 'dev'
+ - setuptools ; extra == 'dev'
+ requires_python: '>=3.8'
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..089ee94
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,42 @@
+[project]
+name = "PREFACE"
+version = "1.0.0dev"
+description = "PREFACE - PREdict FetAl ComponEnt"
+readme = "README.md"
+authors = [
+ { name = "Matthias De Smet", email = "matthias.desmet@ugent.be" },
+]
+requires-python = ">=3.11,<3.14"
+classifiers = [
+ "Programming Language :: Python :: 3",
+ "Operating System :: OS Independent",
+]
+dependencies = [
+ "pandas>=2.3.3,<3",
+ "numpy>=2.3.5,<3",
+ "scikit-learn>=1.8.0,<2",
+ "tensorflow>=2.20.0,<3",
+ "matplotlib>=3.10.8,<4",
+ "joblib>=1.5.3,<2",
+ "statsmodels>=0.14.6,<0.15",
+ "typer>=0.20.0,<0.21",
+]
+
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[project.scripts]
+PREFACE = "preface:app"
+
+[tool.setuptools]
+py-modules = ["preface", "npz_to_parquet"]
+
+[tool.pixi.workspace]
+channels = ["conda-forge"]
+platforms = ["osx-arm64"]
+
+[tool.pixi.pypi-dependencies]
+PREFACE = { path = ".", editable = true }
+
+[tool.pixi.tasks]
diff --git a/src/preface/__init__.py b/src/preface/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/preface/lib/__init__.py b/src/preface/lib/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/preface/predict.py b/src/preface/predict.py
new file mode 100644
index 0000000..8c0e6d3
--- /dev/null
+++ b/src/preface/predict.py
@@ -0,0 +1,103 @@
+
+
+import typer
+import joblib
+import os
+import json
+from typing import Optional, Union
+import pandas as pd
+from sklearn.linear_model import LinearRegression
+
+
+def preface_predict(
+ infile: str = typer.Option(..., "--infile", help="Path to input BED file"),
+ model_path_base: str = typer.Option(
+ ..., "--model", help="Path to model (directory or model_meta.pkl)"
+ ),
+ json_output: Optional[str] = typer.Option(
+ None,
+ "--json",
+ help="Output JSON. If filename provided, writes to file. Pass 'stdout' for console output.",
+ ),
+) -> None:
+ """
+ Predict using model.
+ """
+ if os.path.isdir(model_path_base):
+ meta_path = os.path.join(model_path_base, "model_meta.pkl")
+ else:
+ meta_path = model_path_base
+
+ if not os.path.exists(meta_path):
+ root, _ = os.path.splitext(model_path_base)
+ if os.path.exists(root + ".pkl"):
+ meta_path = root + ".pkl"
+ else:
+ typer.echo(f"The file '{meta_path}' does not exist.")
+ raise typer.Exit(code=1)
+
+ model_data = joblib.load(meta_path)
+
+ n_feat = model_data["n_feat"]
+ mean_features = model_data["mean_features"]
+ possible_features = model_data["possible_features"]
+ pca = model_data["pca"]
+ is_olm = model_data["is_olm"]
+ the_intercept = model_data["the_intercept"]
+ the_slope = model_data["the_slope"]
+ the_intercept_X = model_data["the_intercept_X"]
+ the_slope_X = model_data["the_slope_X"]
+
+ dir_path = os.path.dirname(meta_path)
+ model: Union[LinearRegression, keras.Model]
+ if is_olm:
+ model = joblib.load(os.path.join(dir_path, "model_weights.pkl"))
+ else:
+ model = keras.models.load_model(os.path.join(dir_path, "model_weights.keras"))
+
+ bin_table = pd.read_csv(infile, sep="\t")
+
+ x_bins = bin_table[bin_table["chr"] == "X"]
+ x_ratio: float
+ if len(x_bins) > 0:
+ x_ratio = float(2 ** np.mean(x_bins["ratio"].dropna()))
+ else:
+ x_ratio = float(np.nan)
+
+ FFX: float = (x_ratio - the_intercept_X) / the_slope_X
+
+ bin_table["feat_id"] = (
+ bin_table["chr"].astype(str)
+ + ":"
+ + bin_table["start"].astype(str)
+ + "-"
+ + bin_table["end"].astype(str)
+ )
+
+ ratio_map = bin_table.set_index("feat_id")["ratio"]
+ features = ratio_map.reindex(possible_features)
+ features = features.fillna(mean_features)
+
+ features_array = features.values.reshape(1, -1)
+
+ projected_ratio = pca.transform(features_array)[:, :n_feat]
+
+ prediction: float
+ if is_olm:
+ prediction = float(model.predict(projected_ratio)[0])
+ else:
+ prediction = float(model.predict(projected_ratio).flatten()[0])
+
+ prediction = the_intercept + the_slope * prediction
+
+ json_dict = {"FFX": FFX / 100, "PREFACE": prediction / 100}
+
+ if json_output:
+ if json_output != "stdout" and json_output != "":
+ with open(json_output, "w") as f:
+ json.dump(json_dict, f)
+ else:
+ typer.echo(json.dumps(json_dict))
+ else:
+ typer.echo(f"FFX = {FFX:.4g}%")
+ typer.echo(f"PREFACE = {prediction:.4g}%")
diff --git a/src/preface/preface.py b/src/preface/preface.py
new file mode 100644
index 0000000..8febf88
--- /dev/null
+++ b/src/preface/preface.py
@@ -0,0 +1,23 @@
+import typer
+
+from preface.predict import preface_predict
+from preface.train import preface_train
+from preface.utils.npz_to_parquet import npz_to_parquet
+from preface.utils.ffy import ffy
+
+# Version
+VERSION: str = "1.0.0dev"
+
+# Initialize Typer app
+app = typer.Typer(help="PREFACE - PREdict FetAl ComponEnt")
+app.command(name="predict")(preface_predict)
+app.command(name="train")(preface_train)
+
+# Utilities group
+utils_app = typer.Typer(help="Utility scripts")
+utils_app.command(name="npz-to-parquet")(npz_to_parquet)
+utils_app.command(name="ffy")(ffy)
+app.add_typer(utils_app, name="utils")
+
+if __name__ == "__main__":
+ app()
diff --git a/src/preface/train.py b/src/preface/train.py
new file mode 100755
index 0000000..91e0e70
--- /dev/null
+++ b/src/preface/train.py
@@ -0,0 +1,476 @@
+#!/usr/bin/env python3
+
+import os
+import time
+import json
+from typing import List, Optional, Any, Dict, Union
+
+import numpy as np
+import pandas as pd
+import joblib
+import matplotlib.pyplot as plt
+import statsmodels.api as sm
+from sklearn.decomposition import PCA
+from sklearn.linear_model import LinearRegression
+from joblib import Parallel, delayed
+import tensorflow as tf
+from tensorflow import keras
+from tensorflow.keras import layers
+import typer
+
+
+
+# Constants
+EXCLUDE_CHRS: List[str] = ['13', '18', '21', 'X', 'Y']
+COLOR_A: str = '#8DD1C6'
+COLOR_B: str = '#E3C88A'
+COLOR_C: str = '#C87878'
+
+
+
+def get_m_diff(v1: np.ndarray, v2: np.ndarray, abs_val: bool = True) -> float:
+ if not abs_val:
+ return float(np.mean(v1 - v2))
+ return float(np.mean(np.abs(v1 - v2)))
+
+def get_sd_diff(v1: np.ndarray, v2: np.ndarray) -> float:
+ return float(np.std(np.abs(v1 - v2), ddof=1)) # ddof=1 for sample sd
+
+def plot_performance(
+ v1: np.ndarray,
+ v2: np.ndarray,
+ pca_explained_variance_ratio: np.ndarray,
+ n_feat: int,
+ xlab: str,
+ ylab: str,
+ path: str
+) -> List[float]:
+
+ # R plot layout: 1 row, 3 columns.
+
+ fig, axes = plt.subplots(1, 3, figsize=(15, 5))
+
+ # Plot 1: PCA Importance
+ ax = axes[0]
+ y_vals = pca_explained_variance_ratio
+ x_vals = np.arange(1, len(y_vals) + 1)
+
+ # Filtering zeros for log
+ mask = y_vals > 0
+ x_vals = x_vals[mask]
+ y_vals = y_vals[mask]
+
+ ax.plot(np.log(x_vals), np.log(y_vals), color=COLOR_A, linewidth=2)
+ ax.set_xlabel('Principal components (log scale)')
+ ax.set_ylabel('Proportion of variance (log scale)')
+ ax.set_title('PCA')
+
+ # Vertical line at n_feat
+ log_n_feat = np.log(n_feat)
+ ylim = ax.get_ylim()
+ ax.vlines(log_n_feat, ylim[0], ylim[1] * 0.99, colors=COLOR_C, linestyles='dotted', linewidth=3)
+ ax.text(log_n_feat, ylim[1], 'Number of features', color=COLOR_C, ha='center', va='bottom', fontsize=8)
+
+ # Plot 2: Scatter Plot
+ ax = axes[1]
+ mx = max(float(np.max(v1)), float(np.max(v2)))
+ ax.scatter(v1, v2, s=10, c='black', alpha=0.6)
+ ax.set_xlabel(xlab)
+ ax.set_ylabel(ylab)
+ ax.set_xlim(0, mx)
+ ax.set_ylim(0, mx)
+ ax.set_title('Scatter plot')
+
+ # OLS fit
+ intercept: float = 0.0
+ slope: float = 0.0
+ correlation: float = 0.0
+
+ if len(np.unique(v1)) > 1:
+ reg = LinearRegression().fit(v1.reshape(-1, 1), v2)
+ fit_line = reg.predict(np.array([[0], [mx]]))
+ ax.plot([0, mx], fit_line, color=COLOR_A, linestyle='--', linewidth=2, label='OLS fit')
+ intercept = float(reg.intercept_)
+ slope = float(reg.coef_[0])
+ correlation = float(np.corrcoef(v1, v2)[0, 1])
+ else:
+ # Fallback if v1 is constant
+ mean_v2 = float(np.mean(v2))
+ ax.plot([0, mx], [mean_v2, mean_v2], color=COLOR_A, linestyle='--', linewidth=2, label='Mean fit')
+ intercept = mean_v2
+ slope = 0.0
+ correlation = 0.0
+
+ # Identity line
+ ax.plot([0, mx], [0, mx], color=COLOR_B, linestyle=':', linewidth=3, label='f(x)=x')
+
+ ax.legend()
+ ax.text(0, mx * 1.03, f'(r = {correlation:.3g})', fontsize=9, ha='left')
+
+ # Plot 3: Histogram of errors
+ ax = axes[2]
+ errors = v1 - v2
+ n_bins = max(20, len(v1)//10)
+ counts, bins, patches = ax.hist(errors, bins=n_bins, density=True, color='black', alpha=0.5)
+ ax.set_xlabel(f'{xlab} - {ylab}')
+ ax.set_ylabel('Density')
+ ax.set_title('Histogram')
+
+ mx_hist = float(np.max(counts)) if len(counts) > 0 else 0.1
+ # Mean error line
+ mean_err = get_m_diff(v1, v2, abs_val=False)
+ ax.vlines(mean_err, 0, mx_hist, colors=COLOR_A, linestyles='--', linewidth=3, label='mean error')
+ ax.vlines(0, 0, mx_hist, colors=COLOR_B, linestyles=':', linewidth=3, label='x=0')
+ ax.legend()
+
+ mae = get_m_diff(v1, v2)
+ sd_diff = get_sd_diff(v1, v2)
+ min_bin = float(min(bins)) if len(bins) > 0 else 0.0
+ ax.text(min_bin, mx_hist * 1.03, f'(MAE = {mae:.3g} ± {sd_diff:.3g})', fontsize=9, ha='left')
+
+ plt.tight_layout()
+ plt.savefig(path, dpi=300)
+ plt.close()
+
+ return [intercept, slope, mae, sd_diff, correlation]
+
+def load_bed_file(filepath: str) -> Optional[np.ndarray]:
+ try:
+ # Assuming BED has header
+ df = pd.read_csv(filepath, sep='\t')
+ # Check columns
+ if 'ratio' not in df.columns:
+ # Fallback if no header
+ pass
+
+ df = df[df['chr'] != 'Y']
+ return df['ratio'].values
+ except Exception as e:
+ print(f"Error reading {filepath}: {e}")
+ return None
+
+def load_bed_full(filepath: str) -> pd.DataFrame:
+ # For creating the full training frame with coordinates
+ df = pd.read_csv(filepath, sep='\t')
+ return df
+
+def train_neural_network(X_train: np.ndarray, Y_train: np.ndarray, hidden_units: int) -> keras.Model:
+ model = keras.Sequential([
+ layers.Input(shape=(X_train.shape[1],)),
+ layers.Dense(hidden_units, activation='sigmoid'),
+ layers.Dense(1, activation='linear')
+ ])
+
+ model.compile(optimizer='adam', loss='mse')
+
+ early_stop = keras.callbacks.EarlyStopping(monitor='loss', patience=10, restore_best_weights=True)
+
+ model.fit(X_train, Y_train, epochs=200, batch_size=32, verbose=0, callbacks=[early_stop])
+ return model
+
+
+def preface_train(
+ config_file: str = typer.Option(..., "--config", help="Path to config file"),
+ out_dir: str = typer.Option(..., "--outdir", help="Output directory"),
+ n_feat: int = typer.Option(50, "--nfeat", help="Number of features (PCA components)"),
+ hidden: int = typer.Option(2, "--hidden", help="Hidden units in NN"),
+ cpus: int = typer.Option(1, "--cpus", help="Number of CPUs"),
+ femprop: bool = typer.Option(False, "--femprop", help="Include females in training"),
+ olm: bool = typer.Option(False, "--olm", help="Use Ordinary Linear Model instead of NN"),
+ noskewcorrect: bool = typer.Option(False, "--noskewcorrect", help="Disable skew correction")
+) -> None:
+ """
+ Train the PREFACE model.
+ """
+ start_time = time.time()
+
+ if not os.path.exists(config_file):
+ typer.echo(f"The file '{config_file}' does not exist.")
+ raise typer.Exit(code=1)
+
+ if not os.path.exists(out_dir):
+ os.makedirs(out_dir, exist_ok=True)
+
+ skewcorrect: bool = not noskewcorrect
+ train_gender: List[str] = ['M']
+ if femprop:
+ train_gender = ['M', 'F']
+
+ out_dir_path: str = os.path.join(out_dir, '')
+
+ # Load config
+ config = pd.read_csv(config_file, sep='\t', comment='#', dtype={'gender': str, 'ID': str})
+
+ # Check samples
+ labeled_samples = config[config['gender'].isin(train_gender)]
+ if len(labeled_samples) < n_feat:
+ typer.echo(f"Please provide at least {n_feat} labeled samples.")
+ raise typer.Exit(code=1)
+
+ # Shuffle
+ config = config.sample(frac=1, random_state=1).reset_index(drop=True)
+
+ # Load first file for structure
+ first_path: str = str(config['filepath'].iloc[0])
+ training_frame_meta = load_bed_full(first_path)
+ training_frame_meta = training_frame_meta[['chr', 'start', 'end']]
+
+ # Load all ratios in parallel
+ typer.echo("Loading samples...")
+ results: List[Optional[np.ndarray]] = Parallel(n_jobs=cpus)(delayed(load_bed_file)(str(f)) for f in config['filepath'])
+
+ lengths: List[int] = [len(x) for x in results if x is not None]
+ if len(set(lengths)) > 1:
+ typer.echo("Error: Input BED files have different numbers of bins (excluding Y).")
+ raise typer.Exit(code=1)
+
+ # Filter out Nones and stack
+ valid_results: List[np.ndarray] = [res for res in results if res is not None]
+ training_frame_sub = np.column_stack(valid_results)
+
+ # Ensure meta alignment
+ training_frame_meta = training_frame_meta[training_frame_meta['chr'] != 'Y']
+ if len(training_frame_meta) != training_frame_sub.shape[0]:
+ typer.echo("Mismatch in row counts between metadata and loaded data.")
+ raise typer.Exit(code=1)
+
+ is_x = training_frame_meta['chr'] == 'X'
+ x_ratios_raw = training_frame_sub[is_x, :]
+ x_ratios = 2 ** np.nanmean(x_ratios_raw, axis=0)
+
+ typer.echo("Creating training frame...")
+
+ mask_keep = ~training_frame_meta['chr'].isin(EXCLUDE_CHRS)
+
+ training_frame_filtered = training_frame_sub[mask_keep, :]
+ training_frame_meta_filtered = training_frame_meta[mask_keep]
+
+ # Transpose: Samples as rows, Features as columns
+ training_frame = training_frame_filtered.T
+
+ feature_names = (training_frame_meta_filtered['chr'].astype(str) + ':' +
+ training_frame_meta_filtered['start'].astype(str) + '-' +
+ training_frame_meta_filtered['end'].astype(str)).values
+
+ training_df = pd.DataFrame(training_frame, columns=feature_names)
+
+ # Filter NAs
+ na_threshold = len(config) * 0.01
+ cols_to_keep = training_df.isna().sum() < na_threshold
+ training_df = training_df.loc[:, cols_to_keep]
+
+ possible_features = training_df.columns.values
+ mean_features = training_df.mean()
+
+ training_df = training_df.fillna(mean_features)
+
+ typer.echo(f"Remaining training features after 'NA' filtering: {len(possible_features)}")
+
+ os.makedirs(os.path.join(out_dir_path, 'training_repeats'), exist_ok=True)
+
+ repeats: int = 10
+ test_percentage: float = 1.0 / repeats
+
+ train_mask = config['gender'].isin(train_gender)
+ train_indices_all: List[int] = config.index[train_mask].tolist()
+
+ n_train_samples: int = len(train_indices_all)
+ test_number: int = int(n_train_samples * test_percentage)
+
+ max_feat: int = n_train_samples - test_number - 1
+ if n_feat > max_feat:
+ typer.echo(f"Too few samples were provided for --nfeat {n_feat}, using --nfeat {max_feat}")
+ n_feat = max_feat
+
+ train_subset_df = training_df.iloc[train_indices_all].reset_index(drop=True)
+ y_all: np.ndarray = config.loc[train_indices_all, 'FF'].astype(float).values
+
+ results_repeats: List[Dict[str, Any]] = []
+
+ for i in range(1, repeats + 1):
+ typer.echo(f"Model training | Repeat {i}/{repeats} ...")
+
+ start_idx: int = int((i - 1) * test_number)
+ end_idx: int = int(i * test_number)
+
+ test_idxs_local: List[int] = list(range(start_idx, end_idx))
+ train_idxs_local: List[int] = list(set(range(len(train_subset_df))) - set(test_idxs_local))
+
+ X_tr_local = train_subset_df.iloc[train_idxs_local]
+ X_te_local = train_subset_df.iloc[test_idxs_local]
+ Y_tr_local = y_all[train_idxs_local]
+ Y_te_local = y_all[test_idxs_local]
+
+ typer.echo("\tExecuting principal component analysis ...")
+ n_components_pca: int = min(n_feat * 10, len(X_tr_local) - 1)
+ pca = PCA(n_components=n_components_pca)
+ pca.fit(X_tr_local)
+
+ X_train_pca = pca.transform(X_tr_local)
+ X_test_pca = pca.transform(X_te_local)
+
+ X_train_model = X_train_pca[:, :n_feat]
+ X_test_model = X_test_pca[:, :n_feat]
+
+ prediction: Optional[np.ndarray] = None
+ if olm:
+ typer.echo("\tTraining ordinary linear model ...")
+ model = LinearRegression()
+ model.fit(X_train_model, Y_tr_local)
+ prediction = model.predict(X_test_model)
+ else:
+ typer.echo("\tTraining neural network ...")
+ model = train_neural_network(X_train_model, Y_tr_local, hidden)
+ prediction = model.predict(X_test_model).flatten()
+
+ info = plot_performance(prediction, Y_te_local, pca.explained_variance_ratio_, n_feat,
+ 'PREFACE (%)', 'FF (%)', os.path.join(out_dir_path, 'training_repeats', f'repeat_{i}.png'))
+
+ results_repeats.append({
+ 'intercept': info[0],
+ 'slope': info[1],
+ 'prediction': prediction
+ })
+
+ predictions: np.ndarray = np.concatenate([r['prediction'] for r in results_repeats])
+
+ the_intercept: float = 0.0
+ the_slope: float = 1.0
+
+ n_used: int = int(test_number * repeats)
+ y_used: np.ndarray = y_all[:n_used]
+
+ if skewcorrect:
+ np.random.seed(1)
+ n_pred: int = len(predictions)
+ p: np.ndarray = np.random.choice(n_pred, max(1, n_pred // 4), replace=False)
+
+ pred_p = predictions[p]
+ y_p = y_used[p]
+
+ reg_skew = LinearRegression().fit(pred_p.reshape(-1, 1), y_p)
+ the_intercept = float(reg_skew.intercept_)
+ the_slope = float(reg_skew.coef_[0])
+
+ typer.echo("Correction for skew:")
+ typer.echo(f"\tIntercept: {the_intercept}")
+ typer.echo(f"\tSlope: {the_slope}")
+
+ typer.echo("Training FFX Model...")
+
+ mask_m = config['gender'] == 'M'
+ v1_m: np.ndarray = config.loc[mask_m, 'FF'].astype(float).values
+ v2_m: np.ndarray = x_ratios[mask_m]
+
+ X_rlm = sm.add_constant(v1_m)
+ rlm_model = sm.RLM(v2_m, X_rlm, M=sm.robust.norms.HuberT())
+ rlm_results = rlm_model.fit()
+
+ fit_params = rlm_results.params
+ the_intercept_X: float = fit_params[0]
+ the_slope_X: float = fit_params[1]
+
+ fig, axes = plt.subplots(1, 2, figsize=(10, 5))
+ ax = axes[0]
+ ax.scatter(v1_m, v2_m, s=10, c='black', alpha=0.6)
+ ax.set_xlabel('FF (%)')
+ ax.set_ylabel('μ(ratio X)')
+ mx = max(v1_m) if len(v1_m) > 0 else 1
+ ax.set_xlim(0, mx)
+
+ x_range = np.array([min(v1_m) if len(v1_m)>0 else 0, max(v1_m) if len(v1_m)>0 else 1])
+ y_range = the_intercept_X + the_slope_X * x_range
+ ax.plot(x_range, y_range, color=COLOR_A, linestyle='--', linewidth=2, label='RLS fit')
+ ax.legend()
+
+ ax = axes[1]
+ v2_corrected = (v2_m - the_intercept_X) / the_slope_X if the_slope_X != 0 else v2_m
+ ax.scatter(v1_m, v2_corrected, s=10, c='black', alpha=0.6)
+ ax.set_xlabel('FF (%)')
+ ax.set_ylabel('FFX (%)')
+ ax.set_xlim(0, mx)
+ ax.plot([x_range[0], x_range[1]], [x_range[0], x_range[1]], color=COLOR_B, linestyle=':', linewidth=3)
+
+ plt.tight_layout()
+ plt.savefig(os.path.join(out_dir_path, 'FFX.png'), dpi=300)
+ plt.close()
+
+ predictions_corrected = the_intercept + the_slope * predictions
+
+ typer.echo("Executing final principal component analysis ...")
+
+ pca_final = PCA(n_components=min(n_feat * 10, len(train_subset_df) - 1))
+ pca_final.fit(train_subset_df)
+
+ X_train_final = pca_final.transform(train_subset_df)[:, :n_feat]
+ Y_train_final = y_all
+
+ model_final: Union[LinearRegression, keras.Model]
+ if olm:
+ typer.echo("Training final ordinary linear model ...")
+ model_final = LinearRegression()
+ model_final.fit(X_train_final, Y_train_final)
+ else:
+ typer.echo("Training final neural network ...")
+ model_final = train_neural_network(X_train_final, Y_train_final, hidden)
+
+ info_overall = plot_performance(predictions_corrected, y_used, pca_final.explained_variance_ratio_,
+ n_feat, 'PREFACE (%)', 'FF (%)', os.path.join(out_dir_path, 'overall_performance.png'))
+
+ deviations = np.abs(predictions_corrected - y_used)
+ mae = info_overall[2]
+ sd = info_overall[3]
+ outlier_threshold = mae + 3 * sd
+ outlier_indices = np.where(deviations > outlier_threshold)[0]
+
+ with open(os.path.join(out_dir_path, 'training_statistics.txt'), 'w') as f:
+ f.write('PREFACE - PREdict FetAl ComponEnt\n\n')
+
+ if len(outlier_indices) > 0:
+ f.write('Below, some of the top candidates for outlier removal are listed.\n')
+ f.write('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- _\n')
+ f.write('ID\tFF (%) - PREFACE (%)\n')
+
+ sorted_outlier_idxs = outlier_indices[np.argsort(-deviations[outlier_indices])]
+ subset_ids = config.loc[train_indices_all, 'ID'].values[:n_used]
+ subset_diffs = (predictions_corrected - y_used)
+
+ for idx in sorted_outlier_idxs:
+ f.write(f"{subset_ids[idx]}\t{subset_diffs[idx]:.4f}\n")
+ f.write('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- _\n\n')
+
+ elapsed_time = time.time() - start_time
+ f.write(f"Training time: {elapsed_time:.0f} seconds\n")
+ f.write(f"Overall correlation (r): {info_overall[4]:.4f}\n")
+ f.write(f"Overall mean absolute error (MAE): {info_overall[2]:.4f} ± {info_overall[3]:.4f}\n")
+
+ mask_10 = y_used < 10.0
+ if np.any(mask_10):
+ devs_10 = deviations[mask_10]
+ f.write(f"FF < 10% mean absolute error (MAE): {np.mean(devs_10):.4f} ± {np.std(devs_10, ddof=1):.4f}\n")
+
+ f.write("Correction for skew: \n")
+ f.write(f"\tIntercept: {the_intercept}\n")
+ f.write(f"\tSlope: {the_slope}\n\n")
+
+ model_data = {
+ 'n_feat': n_feat,
+ 'mean_features': mean_features,
+ 'possible_features': possible_features,
+ 'pca': pca_final,
+ 'is_olm': olm,
+ 'the_intercept': the_intercept,
+ 'the_slope': the_slope,
+ 'the_intercept_X': the_intercept_X,
+ 'the_slope_X': the_slope_X,
+ }
+
+ joblib.dump(model_data, os.path.join(out_dir_path, 'model_meta.pkl'))
+
+ if olm:
+ joblib.dump(model_final, os.path.join(out_dir_path, 'model_weights.pkl'))
+ else:
+ model_final.save(os.path.join(out_dir_path, 'model_weights.keras'))
+
+ typer.echo(f"Finished! Consult '{out_dir_path}training_statistics.txt' to analyse your model's performance.")
+
diff --git a/src/preface/utils/__init.py__ b/src/preface/utils/__init.py__
new file mode 100644
index 0000000..e69de29
diff --git a/src/preface/utils/ffy.py b/src/preface/utils/ffy.py
new file mode 100644
index 0000000..35893a9
--- /dev/null
+++ b/src/preface/utils/ffy.py
@@ -0,0 +1,2 @@
+def ffy():
+ pass
\ No newline at end of file
diff --git a/src/preface/utils/npz_to_parquet.py b/src/preface/utils/npz_to_parquet.py
new file mode 100644
index 0000000..df687d3
--- /dev/null
+++ b/src/preface/utils/npz_to_parquet.py
@@ -0,0 +1,85 @@
+import os
+import sys
+from typing import List
+
+import numpy as np
+import pandas as pd
+import typer
+
+
+def _convert_single_npz(npz_path: str, output_dir: str) -> None:
+ """
+ Converts a single NPZ file to one or more Parquet files.
+ """
+ try:
+ npz_data = np.load(npz_path, allow_pickle=True)
+ except Exception as e:
+ typer.echo(f"Error loading {npz_path}: {e}", err=True)
+ return
+
+ base_name = os.path.splitext(os.path.basename(npz_path))[0]
+
+ typer.echo(f"Processing NPZ file: {npz_path}")
+
+ for key in npz_data.files:
+ array = npz_data[key]
+
+ # Determine output filename
+ output_filename = f"{base_name}_{key}.parquet"
+ output_filepath = os.path.join(output_dir, output_filename)
+
+ typer.echo(
+ f" Converting array '{key}' (shape: {array.shape}, dtype: {array.dtype}) to {output_filepath}"
+ )
+
+ # Handle different array dimensions
+ df: pd.DataFrame
+ if array.ndim == 1:
+ # 1D array, convert to a single-column DataFrame
+ df = pd.DataFrame({key: array})
+ elif array.ndim == 2:
+ # 2D array, convert to DataFrame where columns are named 'key_0', 'key_1', etc.
+ # Or if it's a structured array, pandas can handle it directly.
+ if array.dtype.fields: # Check if it's a structured numpy array
+ df = pd.DataFrame(array)
+ else:
+ df = pd.DataFrame(
+ array, columns=[f"{key}_{i}" for i in range(array.shape[1])]
+ )
+ elif array.ndim > 2:
+ typer.echo(
+ f" Warning: Array '{key}' has {array.ndim} dimensions. Flattening for Parquet storage.",
+ err=True,
+ )
+ # Flatten to 1D and then treat as a single-column DataFrame
+ df = pd.DataFrame({key: array.flatten()})
+ else: # Scalar case (ndim == 0)
+ df = pd.DataFrame({key: [array.item()]}) # Store as a single-row DataFrame
+
+ try:
+ df.to_parquet(output_filepath, index=False)
+ typer.echo(f" Successfully saved '{key}' to {output_filepath}")
+ except Exception as e:
+ typer.echo(f" Error saving array '{key}' to Parquet: {e}", err=True)
+
+
+def npz_to_parquet(
+ npz_files: List[str] = typer.Argument(..., help="One or more .npz files to convert."),
+ output_dir: str = typer.Option(
+ ".", "-o", "--output-dir", help="Directory to save the output Parquet files."
+ ),
+) -> None:
+ """
+ Convert NumPy .npz files to Parquet files for easier exploration.
+ """
+ os.makedirs(output_dir, exist_ok=True)
+
+ for npz_file in npz_files:
+ if not os.path.exists(npz_file):
+ typer.echo(f"Error: Input file not found: {npz_file}", err=True)
+ continue
+ _convert_single_npz(npz_file, output_dir)
+
+
+if __name__ == "__main__":
+ typer.run(npz_to_parquet)
\ No newline at end of file
From 3d752462a724edd3c849db4edf22bf3e48757099 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Wed, 17 Dec 2025 08:35:08 +0100
Subject: [PATCH 02/50] Add GHA to publish on release
---
.github/workflows/docker-publish.yml | 36 ++++++++++++++++++++++++++++
.github/workflows/pypi-publish.yml | 34 ++++++++++++++++++++++++++
Dockerfile | 9 +++++++
pyproject.toml | 6 ++---
4 files changed, 82 insertions(+), 3 deletions(-)
create mode 100644 .github/workflows/docker-publish.yml
create mode 100644 .github/workflows/pypi-publish.yml
create mode 100644 Dockerfile
diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
new file mode 100644
index 0000000..773ae0c
--- /dev/null
+++ b/.github/workflows/docker-publish.yml
@@ -0,0 +1,36 @@
+name: Build and Push Docker Image to Quay.io
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ docker-publish:
+ name: Build and Push Docker Image
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Log in to Quay.io
+ uses: docker/login-action@v3
+ with:
+ registry: quay.io
+ username: ${{ secrets.QUAY_USERNAME }}
+ password: ${{ secrets.QUAY_PASSWORD }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build and push
+ uses: docker/build-push-action@v5
+ with:
+ context: .
+ push: true
+ tags: |
+ quay.io/${{ secrets.QUAY_USERNAME }}/preface:latest
+ quay.io/${{ secrets.QUAY_USERNAME }}/preface:${{ github.event.release.tag_name }}
diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml
new file mode 100644
index 0000000..a1c641c
--- /dev/null
+++ b/.github/workflows/pypi-publish.yml
@@ -0,0 +1,34 @@
+name: Publish Python Package to PyPI
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ pypi-publish:
+ name: Build and publish Python distribution to PyPI
+ runs-on: ubuntu-latest
+ permissions:
+ id-token: write
+ contents: read
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+
+ - name: Install build dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install build
+
+ - name: Build package
+ run: python -m build
+
+ - name: Publish to PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..7d927df
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,9 @@
+FROM python:3.13-slim
+
+WORKDIR /app
+
+COPY . /app
+
+RUN pip install .
+
+ENTRYPOINT ["PREFACE"]
diff --git a/pyproject.toml b/pyproject.toml
index 089ee94..8162f1f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -29,12 +29,12 @@ build-backend = "setuptools.build_meta"
[project.scripts]
PREFACE = "preface:app"
-[tool.setuptools]
-py-modules = ["preface", "npz_to_parquet"]
+[tool.setuptools.packages.find]
+where = ["src"]
[tool.pixi.workspace]
channels = ["conda-forge"]
-platforms = ["osx-arm64"]
+platforms = ["osx-arm64","linux-64","linux-aarch64"]
[tool.pixi.pypi-dependencies]
PREFACE = { path = ".", editable = true }
From 4a7288d6eb4ff5a7c695098bed2642d445f55cde Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Wed, 17 Dec 2025 08:43:02 +0100
Subject: [PATCH 03/50] Only set version in one spot
---
.gitignore | 1 +
pyproject.toml | 7 +++++--
src/preface/__init__.py | 1 +
src/preface/preface.py | 3 ++-
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index 2dd0f89..4427018 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.Rhistory
data/
*.egg-info
+__pycache__/
# pixi environments
.pixi/*
!.pixi/config.toml
diff --git a/pyproject.toml b/pyproject.toml
index 8162f1f..2c50668 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "PREFACE"
-version = "1.0.0dev"
+dynamic = ["version"]
description = "PREFACE - PREdict FetAl ComponEnt"
readme = "README.md"
authors = [
@@ -27,11 +27,14 @@ requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project.scripts]
-PREFACE = "preface:app"
+PREFACE = "preface.preface:app"
[tool.setuptools.packages.find]
where = ["src"]
+[tool.setuptools.dynamic]
+version = {attr = "preface.__version__"}
+
[tool.pixi.workspace]
channels = ["conda-forge"]
platforms = ["osx-arm64","linux-64","linux-aarch64"]
diff --git a/src/preface/__init__.py b/src/preface/__init__.py
index e69de29..b459070 100644
--- a/src/preface/__init__.py
+++ b/src/preface/__init__.py
@@ -0,0 +1 @@
+__version__ = "1.0.0dev"
diff --git a/src/preface/preface.py b/src/preface/preface.py
index 8febf88..8ff2e0e 100644
--- a/src/preface/preface.py
+++ b/src/preface/preface.py
@@ -4,9 +4,10 @@
from preface.train import preface_train
from preface.utils.npz_to_parquet import npz_to_parquet
from preface.utils.ffy import ffy
+from preface import __version__
# Version
-VERSION: str = "1.0.0dev"
+VERSION: str = __version__
# Initialize Typer app
app = typer.Typer(help="PREFACE - PREdict FetAl ComponEnt")
From fdf89d344287575c733041b852cf1bd8067651da Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Wed, 17 Dec 2025 08:52:26 +0100
Subject: [PATCH 04/50] add a GHA to check version and changelog on pr to
master
---
.github/workflows/pr-checks.yml | 88 +++++++++++++++++++++++++++++++++
CHANGELOG.md | 24 +++++++++
2 files changed, 112 insertions(+)
create mode 100644 .github/workflows/pr-checks.yml
create mode 100644 CHANGELOG.md
diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml
new file mode 100644
index 0000000..9315cac
--- /dev/null
+++ b/.github/workflows/pr-checks.yml
@@ -0,0 +1,88 @@
+name: PR Checks
+
+on:
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ pre-release-checks:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+
+ - name: Verify Version and Changelog
+ shell: python
+ run: |
+ import sys
+ import re
+ import subprocess
+ import os
+
+ def get_version_from_content(content):
+ match = re.search(r'__version__\s*=\s*["\']([^"\\]+)["\\]', content)
+ if match:
+ return match.group(1)
+ return None
+
+ print("--- Starting Checks ---")
+
+ # 1. Get current version
+ try:
+ with open('src/preface/__init__.py', 'r') as f:
+ current_content = f.read()
+ current_version = get_version_from_content(current_content)
+ if not current_version:
+ print("Error: Could not find __version__ in src/preface/__init__.py")
+ sys.exit(1)
+ print(f"Current version: {current_version}")
+ except FileNotFoundError:
+ print("Error: src/preface/__init__.py not found")
+ sys.exit(1)
+
+ # 2. Check for 'dev' in version
+ if 'dev' in current_version.lower():
+ print("Error: Version contains 'dev'. PRs to master must be release versions.")
+ sys.exit(1)
+
+ # 3. Get master version
+ try:
+ # Fetch origin/master to ensure we have the reference
+ subprocess.run(['git', 'fetch', 'origin', 'master'], check=True, capture_output=True)
+ master_content = subprocess.check_output(['git', 'show', 'origin/master:src/preface/__init__.py']).decode('utf-8')
+ master_version = get_version_from_content(master_content)
+ print(f"Master version: {master_version}")
+ except subprocess.CalledProcessError:
+ print("Warning: Could not fetch version from origin/master (maybe it's the first commit?). Skipping bump check.")
+ master_version = None
+
+ # 4. Check if version bumped
+ if master_version and current_version == master_version:
+ print(f"Error: Version {current_version} has not been bumped compared to master ({master_version}).")
+ sys.exit(1)
+
+ # 5. Check Changelog
+ # Using git diff to check for modified files between origin/master and HEAD
+ try:
+ changed_files_output = subprocess.check_output(['git', 'diff', '--name-only', 'origin/master']).decode('utf-8')
+ changed_files = changed_files_output.splitlines()
+
+ if 'CHANGELOG.md' not in changed_files:
+ print("Error: CHANGELOG.md has not been modified.")
+ print("Changed files found:", changed_files)
+ sys.exit(1)
+ print("CHANGELOG.md modification found.")
+
+ except subprocess.CalledProcessError as e:
+ print(f"Error checking git diff: {e}")
+ sys.exit(1)
+
+ print("--- All checks passed successfully ---")
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..57a8e99
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,24 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [1.0.0] - 2026-01-06
+
+### Added
+- Initial Python based implementation of PREFACE.
+
+### Changed
+
+### Removed
+- Dropped R based implementation of PREFACE.
+
+## [0.1.2] - 2021-01-07
+### Added
+- Previous R based implementation of PREFACE.
+
+### Changed
+
+### Removed
\ No newline at end of file
From b7fb09a0c64955d7d7c8c1de341618d7bea7a983 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Wed, 17 Dec 2025 08:55:53 +0100
Subject: [PATCH 05/50] Add previous releases to changelog
---
CHANGELOG.md | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 57a8e99..35f8ecf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,8 +17,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.1.2] - 2021-01-07
### Added
-- Previous R based implementation of PREFACE.
+- Decreased PCA runtime (irlba is now additional dependency)
+- Made robust vs small training sets for testing purposes (however, models will be inaccurate)
### Changed
-### Removed
\ No newline at end of file
+### Removed
+
+## [0.1.1] - 2019-07-15
+
+### Added
+
+### Changed
+- Updated symbols
+- Updated documentation
+
+### Removed
+
+## [0.1.0] - 2019-02-19
+
+### Added
+
+- First release of PREFACE R package.
+
+### Changed
+
+### Removed
From f0bdb09b7f01ca5cec8a5dba127771145d92809f Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 21 Dec 2025 14:54:33 +0100
Subject: [PATCH 06/50] pylint fixes
---
.github/workflows/pypi-publish.yml | 2 +-
CHANGELOG.md | 5 +
pixi.lock | 1792 ++++++++++++++++++++++++++-
pyproject.toml | 3 +
src/preface/__init__.py | 4 +
src/preface/predict.py | 25 +-
src/preface/preface.py | 4 +
src/preface/train.py | 436 ++++---
src/preface/utils/ffy.py | 39 +-
src/preface/utils/npz_to_parquet.py | 15 +-
10 files changed, 2106 insertions(+), 219 deletions(-)
diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml
index a1c641c..281f886 100644
--- a/.github/workflows/pypi-publish.yml
+++ b/.github/workflows/pypi-publish.yml
@@ -18,7 +18,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
- python-version: "3.11"
+ python-version: "3.13"
- name: Install build dependencies
run: |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35f8ecf..07af242 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,18 +8,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.0.0] - 2026-01-06
### Added
+
- Initial Python based implementation of PREFACE.
### Changed
### Removed
+
- Dropped R based implementation of PREFACE.
## [0.1.2] - 2021-01-07
+
### Added
- Decreased PCA runtime (irlba is now additional dependency)
- Made robust vs small training sets for testing purposes (however, models will be inaccurate)
+
### Changed
### Removed
@@ -29,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
### Changed
+
- Updated symbols
- Updated documentation
diff --git a/pixi.lock b/pixi.lock
index 8d0a7b5..e907434 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -8,22 +8,216 @@ environments:
options:
pypi-prerelease-mode: if-necessary-or-explicit
packages:
+ linux-64:
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py313h78bf25f_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_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/dill-0.4.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-h5347b49_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.11-hc97d973_100_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
+ - pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f5/10/ca162f45a102738958dcec8023062dad0cbc17d1ab99d68c4e4a6c45fb2b/numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+ - pypi: ./
+ linux-aarch64:
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/astroid-4.0.2-py313hd81a959_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_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/dill-0.4.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45-default_h1979696_104.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.3-hfae3067_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-hd65408f_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.1-h86ecc28_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.51.1-h022381a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.2-h1022ec0_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.0-h8e36d6e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.13.11-h4c0d347_100_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h561c983_103.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda
+ - pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/95/03/dc0723a013c7d7c19de5ef29e932c3081df1c14ba582b8b86b5de9db7f0f/numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: ./
osx-arm64:
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/astroid-4.0.2-py313h8f79df9_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_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/dill-0.4.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
@@ -83,11 +277,83 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: ./
packages:
+- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
+ sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726
+ md5: d7c89558ba9fa0495403155b64376d81
+ license: None
+ purls: []
+ size: 2562
+ timestamp: 1578324546067
+- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
+ build_number: 16
+ sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22
+ md5: 73aaf86a425cc6e73fcf236a5a46396d
+ depends:
+ - _libgcc_mutex 0.1 conda_forge
+ - libgomp >=7.5.0
+ constrains:
+ - openmp_impl 9999
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 23621
+ timestamp: 1650670423406
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2
+ build_number: 16
+ sha256: 3702bef2f0a4d38bd8288bbe54aace623602a1343c2cfbefd3fa188e015bebf0
+ md5: 6168d71addc746e8f2b8d57dfd2edcea
+ depends:
+ - libgomp >=7.5.0
+ constrains:
+ - openmp_impl 9999
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 23712
+ timestamp: 1650670790230
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
name: absl-py
version: 2.3.1
sha256: eeecf07f0c2a93ace0772c92e596ace6d3d3996c042b2128459aaae2a76de11d
requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py313h78bf25f_0.conda
+ sha256: dc26da204d67948118207322b563a010720497f14dd4b7b0a385bf69a73016ad
+ md5: 65899d37680aab12f5e33ad07d15d1fd
+ depends:
+ - python >=3.13,<3.14.0a0
+ - python_abi 3.13.* *_cp313
+ license: LGPL-2.1-or-later
+ license_family: LGPL
+ purls:
+ - pkg:pypi/astroid?source=hash-mapping
+ size: 518412
+ timestamp: 1762775793423
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/astroid-4.0.2-py313hd81a959_0.conda
+ sha256: 5cfde3eaf246f4a5fcc02a1b5517b1d68596e2ab85511bf9d4808c75a3810bbe
+ md5: 523b4f671d9639932207ff812bac1870
+ depends:
+ - python >=3.13,<3.14.0a0
+ - python >=3.13,<3.14.0a0 *_cp313
+ - python_abi 3.13.* *_cp313
+ license: LGPL-2.1-or-later
+ license_family: LGPL
+ purls:
+ - pkg:pypi/astroid?source=hash-mapping
+ size: 516800
+ timestamp: 1762775967404
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/astroid-4.0.2-py313h8f79df9_0.conda
+ sha256: a623b49fa4e8ea0de9a30fc391228c68d5e650c6a896f166ae1cd4d3bdf2fcc8
+ md5: 3a4cbaca5012f9235d0b7066b90b2b46
+ depends:
+ - python >=3.13,<3.14.0a0
+ - python >=3.13,<3.14.0a0 *_cp313
+ - python_abi 3.13.* *_cp313
+ license: LGPL-2.1-or-later
+ license_family: LGPL
+ purls:
+ - pkg:pypi/astroid?source=hash-mapping
+ size: 520275
+ timestamp: 1762776294541
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
name: astunparse
version: 1.6.3
@@ -95,6 +361,27 @@ packages:
requires_dist:
- wheel>=0.23.0,<1.0
- six>=1.6.1,<2.0
+- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda
+ sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5
+ md5: 51a19bba1b8ebfb60df25cde030b7ebc
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: bzip2-1.0.6
+ license_family: BSD
+ purls: []
+ size: 260341
+ timestamp: 1757437258798
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_8.conda
+ sha256: d2a296aa0b5f38ed9c264def6cf775c0ccb0f110ae156fcde322f3eccebf2e01
+ md5: 2921ac0b541bf37c69e66bd6d9a43bca
+ depends:
+ - libgcc >=14
+ license: bzip2-1.0.6
+ license_family: BSD
+ purls: []
+ size: 192536
+ timestamp: 1757437302703
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda
sha256: b456200636bd5fecb2bec63f7e0985ad2097cf1b83d60ce0b6968dffa6d02aa1
md5: 58fd217444c2a5701a44244faf518206
@@ -119,11 +406,21 @@ packages:
version: 2025.11.12
sha256: 97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: charset-normalizer
+ version: 3.4.4
+ sha256: 6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed
+ requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
name: charset-normalizer
version: 3.4.4
sha256: e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: charset-normalizer
+ version: 3.4.4
+ sha256: a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894
+ requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
name: click
version: 8.3.1
@@ -131,6 +428,67 @@ packages:
requires_dist:
- colorama ; sys_platform == 'win32'
requires_python: '>=3.10'
+- 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
+ size: 27011
+ timestamp: 1733218222191
+- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: contourpy
+ version: 1.3.3
+ sha256: 4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9
+ requires_dist:
+ - numpy>=1.25
+ - furo ; extra == 'docs'
+ - sphinx>=7.2 ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - bokeh ; extra == 'bokeh'
+ - selenium ; extra == 'bokeh'
+ - contourpy[bokeh,docs] ; extra == 'mypy'
+ - bokeh ; extra == 'mypy'
+ - docutils-stubs ; extra == 'mypy'
+ - mypy==1.17.0 ; extra == 'mypy'
+ - types-pillow ; extra == 'mypy'
+ - contourpy[test-no-images] ; extra == 'test'
+ - matplotlib ; extra == 'test'
+ - pillow ; extra == 'test'
+ - pytest ; extra == 'test-no-images'
+ - pytest-cov ; extra == 'test-no-images'
+ - pytest-rerunfailures ; extra == 'test-no-images'
+ - pytest-xdist ; extra == 'test-no-images'
+ - wurlitzer ; extra == 'test-no-images'
+ requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ name: contourpy
+ version: 1.3.3
+ sha256: 348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286
+ requires_dist:
+ - numpy>=1.25
+ - furo ; extra == 'docs'
+ - sphinx>=7.2 ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - bokeh ; extra == 'bokeh'
+ - selenium ; extra == 'bokeh'
+ - contourpy[bokeh,docs] ; extra == 'mypy'
+ - bokeh ; extra == 'mypy'
+ - docutils-stubs ; extra == 'mypy'
+ - mypy==1.17.0 ; extra == 'mypy'
+ - types-pillow ; extra == 'mypy'
+ - contourpy[test-no-images] ; extra == 'test'
+ - matplotlib ; extra == 'test'
+ - pillow ; extra == 'test'
+ - pytest ; extra == 'test-no-images'
+ - pytest-cov ; extra == 'test-no-images'
+ - pytest-rerunfailures ; extra == 'test-no-images'
+ - pytest-xdist ; extra == 'test-no-images'
+ - wurlitzer ; extra == 'test-no-images'
+ requires_python: '>=3.11'
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
name: contourpy
version: 1.3.3
@@ -169,6 +527,18 @@ packages:
- pytest-cov ; extra == 'tests'
- pytest-xdist ; extra == 'tests'
requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
+ sha256: c0c91bd91e59940091cec1760db51a82a58e9c64edf4b808bd2da94201ccfdb4
+ md5: eec5b361dbbaa69dba05050977a414b0
+ depends:
+ - python >=3.10
+ - python
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/dill?source=hash-mapping
+ size: 94889
+ timestamp: 1764517905571
- pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
name: flatbuffers
version: 25.9.23
@@ -207,6 +577,74 @@ packages:
- skia-pathops>=0.5.0 ; extra == 'all'
- uharfbuzz>=0.45.0 ; extra == 'all'
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
+ name: fonttools
+ version: 4.61.1
+ sha256: 64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5
+ requires_dist:
+ - lxml>=4.0 ; extra == 'lxml'
+ - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
+ - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff'
+ - zopfli>=0.1.4 ; extra == 'woff'
+ - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode'
+ - lz4>=1.7.4.2 ; extra == 'graphite'
+ - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable'
+ - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable'
+ - pycairo ; extra == 'interpolatable'
+ - matplotlib ; extra == 'plot'
+ - sympy ; extra == 'symfont'
+ - xattr ; sys_platform == 'darwin' and extra == 'type1'
+ - skia-pathops>=0.5.0 ; extra == 'pathops'
+ - uharfbuzz>=0.45.0 ; extra == 'repacker'
+ - lxml>=4.0 ; extra == 'all'
+ - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all'
+ - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all'
+ - zopfli>=0.1.4 ; extra == 'all'
+ - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all'
+ - lz4>=1.7.4.2 ; extra == 'all'
+ - scipy ; platform_python_implementation != 'PyPy' and extra == 'all'
+ - munkres ; platform_python_implementation == 'PyPy' and extra == 'all'
+ - pycairo ; extra == 'all'
+ - matplotlib ; extra == 'all'
+ - sympy ; extra == 'all'
+ - xattr ; sys_platform == 'darwin' and extra == 'all'
+ - skia-pathops>=0.5.0 ; extra == 'all'
+ - uharfbuzz>=0.45.0 ; extra == 'all'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: fonttools
+ version: 4.61.1
+ sha256: 4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd
+ requires_dist:
+ - lxml>=4.0 ; extra == 'lxml'
+ - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
+ - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff'
+ - zopfli>=0.1.4 ; extra == 'woff'
+ - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode'
+ - lz4>=1.7.4.2 ; extra == 'graphite'
+ - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable'
+ - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable'
+ - pycairo ; extra == 'interpolatable'
+ - matplotlib ; extra == 'plot'
+ - sympy ; extra == 'symfont'
+ - xattr ; sys_platform == 'darwin' and extra == 'type1'
+ - skia-pathops>=0.5.0 ; extra == 'pathops'
+ - uharfbuzz>=0.45.0 ; extra == 'repacker'
+ - lxml>=4.0 ; extra == 'all'
+ - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all'
+ - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all'
+ - zopfli>=0.1.4 ; extra == 'all'
+ - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all'
+ - lz4>=1.7.4.2 ; extra == 'all'
+ - scipy ; platform_python_implementation != 'PyPy' and extra == 'all'
+ - munkres ; platform_python_implementation == 'PyPy' and extra == 'all'
+ - pycairo ; extra == 'all'
+ - matplotlib ; extra == 'all'
+ - sympy ; extra == 'all'
+ - xattr ; sys_platform == 'darwin' and extra == 'all'
+ - skia-pathops>=0.5.0 ; extra == 'all'
+ - uharfbuzz>=0.45.0 ; extra == 'all'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
name: gast
version: 0.7.0
@@ -218,6 +656,14 @@ packages:
sha256: b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed
requires_dist:
- six
+- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ name: grpcio
+ version: 1.76.0
+ sha256: 61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae
+ requires_dist:
+ - typing-extensions~=4.12
+ - grpcio-tools>=1.76.0 ; extra == 'protobuf'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
name: grpcio
version: 1.76.0
@@ -226,6 +672,14 @@ packages:
- typing-extensions~=4.12
- grpcio-tools>=1.76.0 ; extra == 'protobuf'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
+ name: grpcio
+ version: 1.76.0
+ sha256: 83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3
+ requires_dist:
+ - typing-extensions~=4.12
+ - grpcio-tools>=1.76.0 ; extra == 'protobuf'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
name: h5py
version: 3.15.1
@@ -233,6 +687,20 @@ packages:
requires_dist:
- numpy>=1.21.2
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ name: h5py
+ version: 3.15.1
+ sha256: d8cb02c3a96255149ed3ac811eeea25b655d959c6dd5ce702c9a95ff11859eb5
+ requires_dist:
+ - numpy>=1.21.2
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: h5py
+ version: 3.15.1
+ sha256: 121b2b7a4c1915d63737483b7bff14ef253020f617c2fb2811f67a4bed9ac5e8
+ requires_dist:
+ - numpy>=1.21.2
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
name: idna
version: '3.11'
@@ -243,6 +711,31 @@ packages:
- pytest>=8.3.2 ; extra == 'all'
- flake8>=7.1.1 ; extra == 'all'
requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745
+ md5: 63ccfdc3a3ce25b027b8767eb722fca8
+ depends:
+ - python >=3.9
+ - zipp >=3.20
+ - python
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/importlib-metadata?source=hash-mapping
+ size: 34641
+ timestamp: 1747934053147
+- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
+ sha256: 13b0005877f553eb2e5c50447c9d0047e7257124ec2d1569d7dad35697790237
+ md5: 55a61979242077b2cc377c74326ea9f0
+ depends:
+ - importlib-metadata >=4.6.0
+ - python >=3.10,<4.0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/isort?source=hash-mapping
+ size: 74876
+ timestamp: 1760192714356
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
name: joblib
version: 1.5.3
@@ -267,10 +760,78 @@ packages:
version: 1.4.9
sha256: 1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
+ name: kiwisolver
+ version: 1.4.9
+ sha256: 5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ name: kiwisolver
+ version: 1.4.9
+ sha256: b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098
+ requires_python: '>=3.10'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda
+ sha256: 9e191baf2426a19507f1d0a17be0fdb7aa155cdf0f61d5a09c808e0a69464312
+ md5: a6abd2796fc332536735f68ba23f7901
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - zstd >=1.5.7,<1.6.0a0
+ constrains:
+ - binutils_impl_linux-64 2.45
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 725545
+ timestamp: 1764007826689
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45-default_h1979696_104.conda
+ sha256: 7a13072581fa23f658a04f62f62c4677c57d3c9696fbc01cc954a88fc354b44d
+ md5: 28035705fe0c977ea33963489cd008ad
+ depends:
+ - zstd >=1.5.7,<1.6.0a0
+ constrains:
+ - binutils_impl_linux-aarch64 2.45
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 875534
+ timestamp: 1764007911054
+- pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
+ name: libclang
+ version: 18.1.1
+ sha256: c533091d8a3bbf7460a00cb6c1a71da93bffe148f172c7d03b1c31fbf8aa2a0b
+- pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
+ name: libclang
+ version: 18.1.1
+ sha256: 54dda940a4a0491a9d1532bf071ea3ef26e6dbaf03b5000ed94dd7174e8f9592
- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
name: libclang
version: 18.1.1
sha256: 0b2e143f0fac830156feb56f9231ff8338c20aecfe72b4ffe96f19e5a1dbb69a
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda
+ sha256: 1e1b08f6211629cbc2efe7a5bca5953f8f6b3cae0eeb04ca4dacee1bd4e2db2f
+ md5: 8b09ae86839581147ef2e5c5e229d164
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ constrains:
+ - expat 2.7.3.*
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 76643
+ timestamp: 1763549731408
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.3-hfae3067_0.conda
+ sha256: cc2581a78315418cc2e0bb2a273d37363203e79cefe78ba6d282fed546262239
+ md5: b414e36fbb7ca122030276c75fa9c34a
+ depends:
+ - libgcc >=14
+ constrains:
+ - expat 2.7.3.*
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 76201
+ timestamp: 1763549910086
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98
md5: b79875dbb5b1db9a4a22a4520f918e1a
@@ -283,6 +844,27 @@ packages:
purls: []
size: 67800
timestamp: 1763549994166
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda
+ sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54
+ md5: 35f29eec58405aaf55e01cb470d8c26a
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 57821
+ timestamp: 1760295480630
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-hd65408f_0.conda
+ sha256: 6c3332e78a975e092e54f87771611db81dcb5515a3847a3641021621de76caea
+ md5: 0c5ad486dcfb188885e3cf8ba209b97b
+ depends:
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 55586
+ timestamp: 1760295405021
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f
md5: 411ff7cd5d1472bba0f55c0faf04453b
@@ -293,6 +875,74 @@ packages:
purls: []
size: 40251
timestamp: 1760295839166
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda
+ sha256: 6eed58051c2e12b804d53ceff5994a350c61baf117ec83f5f10c953a3f311451
+ md5: 6d0363467e6ed84f11435eb309f2ff06
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _openmp_mutex >=4.5
+ constrains:
+ - libgcc-ng ==15.2.0=*_16
+ - libgomp 15.2.0 he0feb66_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 1042798
+ timestamp: 1765256792743
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_16.conda
+ sha256: 44bfc6fe16236babb271e0c693fe7fd978f336542e23c9c30e700483796ed30b
+ md5: cf9cd6739a3b694dcf551d898e112331
+ depends:
+ - _openmp_mutex >=4.5
+ constrains:
+ - libgomp 15.2.0 h8acb6b2_16
+ - libgcc-ng ==15.2.0=*_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 620637
+ timestamp: 1765256938043
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda
+ sha256: 5b3e5e4e9270ecfcd48f47e3a68f037f5ab0f529ccb223e8e5d5ac75a58fc687
+ md5: 26c46f90d0e727e95c6c9498a33a09f3
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 603284
+ timestamp: 1765256703881
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_16.conda
+ sha256: 0a9d77c920db691eb42b78c734d70c5a1d00b3110c0867cfff18e9dd69bc3c29
+ md5: 4d2f224e8186e7881d53e3aead912f6c
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 587924
+ timestamp: 1765256821307
+- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda
+ sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8
+ md5: 1a580f7796c7bf6393fddb8bbbde58dc
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ constrains:
+ - xz 5.8.1.*
+ license: 0BSD
+ purls: []
+ size: 112894
+ timestamp: 1749230047870
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.1-h86ecc28_2.conda
+ sha256: 498ea4b29155df69d7f20990a7028d75d91dbea24d04b2eb8a3d6ef328806849
+ md5: 7d362346a479256857ab338588190da0
+ depends:
+ - libgcc >=13
+ constrains:
+ - xz 5.8.1.*
+ license: 0BSD
+ purls: []
+ size: 125103
+ timestamp: 1749232230009
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda
sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285
md5: d6df911d4564d77c4374b02552cb17d1
@@ -304,6 +954,27 @@ packages:
purls: []
size: 92286
timestamp: 1749230283517
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda
+ sha256: 3aa92d4074d4063f2a162cd8ecb45dccac93e543e565c01a787e16a43501f7ee
+ md5: c7e925f37e3b40d893459e625f6a53f1
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 91183
+ timestamp: 1748393666725
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-h86ecc28_0.conda
+ sha256: ef8697f934c80b347bf9d7ed45650928079e303bad01bd064995b0e3166d6e7a
+ md5: 78cfed3f76d6f3f279736789d319af76
+ depends:
+ - libgcc >=13
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 114064
+ timestamp: 1748393729243
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda
sha256: 0a1875fc1642324ebd6c4ac864604f3f18f57fbcf558a8264f6ced028a3c75b2
md5: 85ccccb47823dd9f7a99d2c7f530342f
@@ -314,6 +985,27 @@ packages:
purls: []
size: 71829
timestamp: 1748393749336
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda
+ sha256: 6f0e8a812e8e33a4d8b7a0e595efe28373080d27b78ee4828aa4f6649a088454
+ md5: 2e1b84d273b01835256e53fd938de355
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: blessing
+ purls: []
+ size: 938979
+ timestamp: 1764359444435
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.51.1-h022381a_0.conda
+ sha256: e394dd772b71dbcd653d078f3aacf6e26e3478bd6736a687ab86e463a2f153a8
+ md5: 233efdd411317d2dc5fde72464b3df7a
+ depends:
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: blessing
+ purls: []
+ size: 939207
+ timestamp: 1764359457549
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda
sha256: a46b167447e2a9e38586320c30b29e3b68b6f7e6b873c18d6b1aa2efd2626917
md5: 67e50e5bd4e5e2310d66b88c4da50096
@@ -324,6 +1016,52 @@ packages:
purls: []
size: 906292
timestamp: 1764359907797
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-h5347b49_1.conda
+ sha256: 030447cf827c471abd37092ab9714fde82b8222106f22fde94bc7a64e2704c40
+ md5: 41f5c09a211985c3ce642d60721e7c3e
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 40235
+ timestamp: 1764790744114
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.2-h1022ec0_1.conda
+ sha256: 3113c857e36779d94cf9a18236a710ceca0e94230b3bfeba0d134f33ee8c9ecd
+ md5: 15b2cc72b9b05bcb141810b1bada654f
+ depends:
+ - libgcc >=14
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 43415
+ timestamp: 1764790752623
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
+ sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4
+ md5: edb0dca6bc32e4f4789199455a1dbeb8
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ constrains:
+ - zlib 1.3.1 *_2
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 60963
+ timestamp: 1727963148474
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda
+ sha256: 5a2c1eeef69342e88a98d1d95bff1603727ab1ff4ee0e421522acd8813439b84
+ md5: 08aad7cbe9f5a6b460d0976076b6ae64
+ depends:
+ - libgcc >=13
+ constrains:
+ - zlib 1.3.1 *_2
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 66657
+ timestamp: 1727963199518
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b
md5: 369964e85dc26bfe78f41399b366c435
@@ -384,11 +1122,59 @@ packages:
- pytest-regressions ; extra == 'testing'
- requests ; extra == 'testing'
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: markupsafe
+ version: 3.0.3
+ sha256: 133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
name: markupsafe
version: 3.0.3
sha256: 116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: markupsafe
+ version: 3.0.3
+ sha256: ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ name: matplotlib
+ version: 3.10.8
+ sha256: 646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce
+ requires_dist:
+ - contourpy>=1.0.1
+ - cycler>=0.10
+ - fonttools>=4.22.0
+ - kiwisolver>=1.3.1
+ - numpy>=1.23
+ - packaging>=20.0
+ - pillow>=8
+ - pyparsing>=3
+ - python-dateutil>=2.7
+ - meson-python>=0.13.1,<0.17.0 ; extra == 'dev'
+ - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev'
+ - setuptools-scm>=7 ; extra == 'dev'
+ - setuptools>=64 ; extra == 'dev'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ name: matplotlib
+ version: 3.10.8
+ sha256: a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486
+ requires_dist:
+ - contourpy>=1.0.1
+ - cycler>=0.10
+ - fonttools>=4.22.0
+ - kiwisolver>=1.3.1
+ - numpy>=1.23
+ - packaging>=20.0
+ - pillow>=8
+ - pyparsing>=3
+ - python-dateutil>=2.7
+ - meson-python>=0.13.1,<0.17.0 ; extra == 'dev'
+ - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev'
+ - setuptools-scm>=7 ; extra == 'dev'
+ - setuptools>=64 ; extra == 'dev'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
name: matplotlib
version: 3.10.8
@@ -408,11 +1194,38 @@ packages:
- setuptools-scm>=7 ; extra == 'dev'
- setuptools>=64 ; extra == 'dev'
requires_python: '>=3.10'
+- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
+ sha256: 9b0037171dad0100f0296699a11ae7d355237b55f42f9094aebc0f41512d96a1
+ md5: 827064ddfe0de2917fb29f1da4f8f533
+ depends:
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/mccabe?source=hash-mapping
+ size: 12934
+ timestamp: 1733216573915
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
name: mdurl
version: 0.1.2
sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ name: ml-dtypes
+ version: 0.5.4
+ sha256: ce756d3a10d0c4067172804c9cc276ba9cc0ff47af9078ad439b075d1abdc29b
+ requires_dist:
+ - numpy>=1.21
+ - numpy>=1.21.2 ; python_full_version >= '3.10'
+ - numpy>=1.23.3 ; python_full_version >= '3.11'
+ - numpy>=1.26.0 ; python_full_version >= '3.12'
+ - numpy>=2.1.0 ; python_full_version >= '3.13'
+ - absl-py ; extra == 'dev'
+ - pytest ; extra == 'dev'
+ - pytest-xdist ; extra == 'dev'
+ - pylint>=2.6.0 ; extra == 'dev'
+ - pyink ; extra == 'dev'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
name: ml-dtypes
version: 0.5.4
@@ -429,10 +1242,45 @@ packages:
- pylint>=2.6.0 ; extra == 'dev'
- pyink ; extra == 'dev'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: ml-dtypes
+ version: 0.5.4
+ sha256: 533ce891ba774eabf607172254f2e7260ba5f57bdd64030c9a4fcfbd99815d0d
+ requires_dist:
+ - numpy>=1.21
+ - numpy>=1.21.2 ; python_full_version >= '3.10'
+ - numpy>=1.23.3 ; python_full_version >= '3.11'
+ - numpy>=1.26.0 ; python_full_version >= '3.12'
+ - numpy>=2.1.0 ; python_full_version >= '3.13'
+ - absl-py ; extra == 'dev'
+ - pytest ; extra == 'dev'
+ - pytest-xdist ; extra == 'dev'
+ - pylint>=2.6.0 ; extra == 'dev'
+ - pyink ; extra == 'dev'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
name: namex
version: 0.1.0
sha256: e2012a474502f1e2251267062aae3114611f07df4224b6e06334c57b0f2ce87c
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
+ sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586
+ md5: 47e340acb35de30501a76c7c799c41d7
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ license: X11 AND BSD-3-Clause
+ purls: []
+ size: 891641
+ timestamp: 1738195959188
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda
+ sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468
+ md5: 182afabe009dc78d8b73100255ee6868
+ depends:
+ - libgcc >=13
+ license: X11 AND BSD-3-Clause
+ purls: []
+ size: 926034
+ timestamp: 1738196018799
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733
md5: 068d497125e4bf8a66bf707254fff5ae
@@ -447,6 +1295,39 @@ packages:
version: 2.3.5
sha256: aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188
requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/95/03/dc0723a013c7d7c19de5ef29e932c3081df1c14ba582b8b86b5de9db7f0f/numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ name: numpy
+ version: 2.3.5
+ sha256: 9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d
+ requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/f5/10/ca162f45a102738958dcec8023062dad0cbc17d1ab99d68c4e4a6c45fb2b/numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: numpy
+ version: 2.3.5
+ sha256: 11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017
+ requires_python: '>=3.11'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
+ sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d
+ md5: 9ee58d5c534af06558933af3c845a780
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - ca-certificates
+ - libgcc >=14
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 3165399
+ timestamp: 1762839186699
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.0-h8e36d6e_0.conda
+ sha256: 8dd3b4c31fe176a3e51c5729b2c7f4c836a2ce3bd5c82082dc2a503ba9ee0af3
+ md5: 7624c6e01aecba942e9115e0f5a2af9d
+ depends:
+ - ca-certificates
+ - libgcc >=14
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 3705625
+ timestamp: 1762841024958
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
sha256: ebe93dafcc09e099782fe3907485d4e1671296bc14f8c383cb6f3dfebb773988
md5: b34dc4172653c13dcf453862f251af2b
@@ -503,11 +1384,273 @@ packages:
- numpy ; extra == 'docs'
- torch ; extra == 'docs'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- name: packaging
- version: '25.0'
- sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484
- requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: optree
+ version: 0.18.0
+ sha256: 328857d7a35129904b21164f6b0c2ff1d728ad1f5838589c5f437a16c94213c8
+ requires_dist:
+ - typing-extensions>=4.6.0
+ - typing-extensions>=4.12.0 ; python_full_version >= '3.13'
+ - jax ; extra == 'jax'
+ - numpy ; extra == 'numpy'
+ - torch ; extra == 'torch'
+ - ruff ; extra == 'lint'
+ - pylint[spelling] ; extra == 'lint'
+ - mypy ; extra == 'lint'
+ - doc8 ; extra == 'lint'
+ - pyenchant ; extra == 'lint'
+ - xdoctest ; extra == 'lint'
+ - cpplint ; extra == 'lint'
+ - pre-commit ; extra == 'lint'
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - covdefaults ; extra == 'test'
+ - rich ; extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'linux' and extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'darwin' and extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'win32' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'linux' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'darwin' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'win32' and extra == 'test'
+ - sphinx ; extra == 'docs'
+ - sphinx-autoapi ; extra == 'docs'
+ - sphinx-autobuild ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - sphinx-rtd-theme ; extra == 'docs'
+ - sphinxcontrib-bibtex ; extra == 'docs'
+ - sphinx-autodoc-typehints ; extra == 'docs'
+ - docutils ; extra == 'docs'
+ - jax[cpu] ; extra == 'docs'
+ - numpy ; extra == 'docs'
+ - torch ; extra == 'docs'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ name: optree
+ version: 0.18.0
+ sha256: 27611c6c122745a003b5be7aedba49ef86e9fef46d743c234596de0bde6dc679
+ requires_dist:
+ - typing-extensions>=4.6.0
+ - typing-extensions>=4.12.0 ; python_full_version >= '3.13'
+ - jax ; extra == 'jax'
+ - numpy ; extra == 'numpy'
+ - torch ; extra == 'torch'
+ - ruff ; extra == 'lint'
+ - pylint[spelling] ; extra == 'lint'
+ - mypy ; extra == 'lint'
+ - doc8 ; extra == 'lint'
+ - pyenchant ; extra == 'lint'
+ - xdoctest ; extra == 'lint'
+ - cpplint ; extra == 'lint'
+ - pre-commit ; extra == 'lint'
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - covdefaults ; extra == 'test'
+ - rich ; extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'linux' and extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'darwin' and extra == 'test'
+ - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'win32' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'linux' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'darwin' and extra == 'test'
+ - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'win32' and extra == 'test'
+ - sphinx ; extra == 'docs'
+ - sphinx-autoapi ; extra == 'docs'
+ - sphinx-autobuild ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - sphinx-rtd-theme ; extra == 'docs'
+ - sphinxcontrib-bibtex ; extra == 'docs'
+ - sphinx-autodoc-typehints ; extra == 'docs'
+ - docutils ; extra == 'docs'
+ - jax[cpu] ; extra == 'docs'
+ - numpy ; extra == 'docs'
+ - torch ; extra == 'docs'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
+ name: packaging
+ version: '25.0'
+ sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
+ name: pandas
+ version: 2.3.3
+ sha256: 318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac
+ requires_dist:
+ - numpy>=1.22.4 ; python_full_version < '3.11'
+ - numpy>=1.23.2 ; python_full_version == '3.11.*'
+ - numpy>=1.26.0 ; python_full_version >= '3.12'
+ - python-dateutil>=2.8.2
+ - pytz>=2020.1
+ - tzdata>=2022.7
+ - hypothesis>=6.46.1 ; extra == 'test'
+ - pytest>=7.3.2 ; extra == 'test'
+ - pytest-xdist>=2.2.0 ; extra == 'test'
+ - pyarrow>=10.0.1 ; extra == 'pyarrow'
+ - bottleneck>=1.3.6 ; extra == 'performance'
+ - numba>=0.56.4 ; extra == 'performance'
+ - numexpr>=2.8.4 ; extra == 'performance'
+ - scipy>=1.10.0 ; extra == 'computation'
+ - xarray>=2022.12.0 ; extra == 'computation'
+ - fsspec>=2022.11.0 ; extra == 'fss'
+ - s3fs>=2022.11.0 ; extra == 'aws'
+ - gcsfs>=2022.11.0 ; extra == 'gcp'
+ - pandas-gbq>=0.19.0 ; extra == 'gcp'
+ - odfpy>=1.4.1 ; extra == 'excel'
+ - openpyxl>=3.1.0 ; extra == 'excel'
+ - python-calamine>=0.1.7 ; extra == 'excel'
+ - pyxlsb>=1.0.10 ; extra == 'excel'
+ - xlrd>=2.0.1 ; extra == 'excel'
+ - xlsxwriter>=3.0.5 ; extra == 'excel'
+ - pyarrow>=10.0.1 ; extra == 'parquet'
+ - pyarrow>=10.0.1 ; extra == 'feather'
+ - tables>=3.8.0 ; extra == 'hdf5'
+ - pyreadstat>=1.2.0 ; extra == 'spss'
+ - sqlalchemy>=2.0.0 ; extra == 'postgresql'
+ - psycopg2>=2.9.6 ; extra == 'postgresql'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql'
+ - sqlalchemy>=2.0.0 ; extra == 'mysql'
+ - pymysql>=1.0.2 ; extra == 'mysql'
+ - sqlalchemy>=2.0.0 ; extra == 'sql-other'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other'
+ - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other'
+ - beautifulsoup4>=4.11.2 ; extra == 'html'
+ - html5lib>=1.1 ; extra == 'html'
+ - lxml>=4.9.2 ; extra == 'html'
+ - lxml>=4.9.2 ; extra == 'xml'
+ - matplotlib>=3.6.3 ; extra == 'plot'
+ - jinja2>=3.1.2 ; extra == 'output-formatting'
+ - tabulate>=0.9.0 ; extra == 'output-formatting'
+ - pyqt5>=5.15.9 ; extra == 'clipboard'
+ - qtpy>=2.3.0 ; extra == 'clipboard'
+ - zstandard>=0.19.0 ; extra == 'compression'
+ - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'all'
+ - adbc-driver-sqlite>=0.8.0 ; extra == 'all'
+ - beautifulsoup4>=4.11.2 ; extra == 'all'
+ - bottleneck>=1.3.6 ; extra == 'all'
+ - dataframe-api-compat>=0.1.7 ; extra == 'all'
+ - fastparquet>=2022.12.0 ; extra == 'all'
+ - fsspec>=2022.11.0 ; extra == 'all'
+ - gcsfs>=2022.11.0 ; extra == 'all'
+ - html5lib>=1.1 ; extra == 'all'
+ - hypothesis>=6.46.1 ; extra == 'all'
+ - jinja2>=3.1.2 ; extra == 'all'
+ - lxml>=4.9.2 ; extra == 'all'
+ - matplotlib>=3.6.3 ; extra == 'all'
+ - numba>=0.56.4 ; extra == 'all'
+ - numexpr>=2.8.4 ; extra == 'all'
+ - odfpy>=1.4.1 ; extra == 'all'
+ - openpyxl>=3.1.0 ; extra == 'all'
+ - pandas-gbq>=0.19.0 ; extra == 'all'
+ - psycopg2>=2.9.6 ; extra == 'all'
+ - pyarrow>=10.0.1 ; extra == 'all'
+ - pymysql>=1.0.2 ; extra == 'all'
+ - pyqt5>=5.15.9 ; extra == 'all'
+ - pyreadstat>=1.2.0 ; extra == 'all'
+ - pytest>=7.3.2 ; extra == 'all'
+ - pytest-xdist>=2.2.0 ; extra == 'all'
+ - python-calamine>=0.1.7 ; extra == 'all'
+ - pyxlsb>=1.0.10 ; extra == 'all'
+ - qtpy>=2.3.0 ; extra == 'all'
+ - scipy>=1.10.0 ; extra == 'all'
+ - s3fs>=2022.11.0 ; extra == 'all'
+ - sqlalchemy>=2.0.0 ; extra == 'all'
+ - tables>=3.8.0 ; extra == 'all'
+ - tabulate>=0.9.0 ; extra == 'all'
+ - xarray>=2022.12.0 ; extra == 'all'
+ - xlrd>=2.0.1 ; extra == 'all'
+ - xlsxwriter>=3.0.5 ; extra == 'all'
+ - zstandard>=0.19.0 ; extra == 'all'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
+ name: pandas
+ version: 2.3.3
+ sha256: e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d
+ requires_dist:
+ - numpy>=1.22.4 ; python_full_version < '3.11'
+ - numpy>=1.23.2 ; python_full_version == '3.11.*'
+ - numpy>=1.26.0 ; python_full_version >= '3.12'
+ - python-dateutil>=2.8.2
+ - pytz>=2020.1
+ - tzdata>=2022.7
+ - hypothesis>=6.46.1 ; extra == 'test'
+ - pytest>=7.3.2 ; extra == 'test'
+ - pytest-xdist>=2.2.0 ; extra == 'test'
+ - pyarrow>=10.0.1 ; extra == 'pyarrow'
+ - bottleneck>=1.3.6 ; extra == 'performance'
+ - numba>=0.56.4 ; extra == 'performance'
+ - numexpr>=2.8.4 ; extra == 'performance'
+ - scipy>=1.10.0 ; extra == 'computation'
+ - xarray>=2022.12.0 ; extra == 'computation'
+ - fsspec>=2022.11.0 ; extra == 'fss'
+ - s3fs>=2022.11.0 ; extra == 'aws'
+ - gcsfs>=2022.11.0 ; extra == 'gcp'
+ - pandas-gbq>=0.19.0 ; extra == 'gcp'
+ - odfpy>=1.4.1 ; extra == 'excel'
+ - openpyxl>=3.1.0 ; extra == 'excel'
+ - python-calamine>=0.1.7 ; extra == 'excel'
+ - pyxlsb>=1.0.10 ; extra == 'excel'
+ - xlrd>=2.0.1 ; extra == 'excel'
+ - xlsxwriter>=3.0.5 ; extra == 'excel'
+ - pyarrow>=10.0.1 ; extra == 'parquet'
+ - pyarrow>=10.0.1 ; extra == 'feather'
+ - tables>=3.8.0 ; extra == 'hdf5'
+ - pyreadstat>=1.2.0 ; extra == 'spss'
+ - sqlalchemy>=2.0.0 ; extra == 'postgresql'
+ - psycopg2>=2.9.6 ; extra == 'postgresql'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql'
+ - sqlalchemy>=2.0.0 ; extra == 'mysql'
+ - pymysql>=1.0.2 ; extra == 'mysql'
+ - sqlalchemy>=2.0.0 ; extra == 'sql-other'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other'
+ - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other'
+ - beautifulsoup4>=4.11.2 ; extra == 'html'
+ - html5lib>=1.1 ; extra == 'html'
+ - lxml>=4.9.2 ; extra == 'html'
+ - lxml>=4.9.2 ; extra == 'xml'
+ - matplotlib>=3.6.3 ; extra == 'plot'
+ - jinja2>=3.1.2 ; extra == 'output-formatting'
+ - tabulate>=0.9.0 ; extra == 'output-formatting'
+ - pyqt5>=5.15.9 ; extra == 'clipboard'
+ - qtpy>=2.3.0 ; extra == 'clipboard'
+ - zstandard>=0.19.0 ; extra == 'compression'
+ - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard'
+ - adbc-driver-postgresql>=0.8.0 ; extra == 'all'
+ - adbc-driver-sqlite>=0.8.0 ; extra == 'all'
+ - beautifulsoup4>=4.11.2 ; extra == 'all'
+ - bottleneck>=1.3.6 ; extra == 'all'
+ - dataframe-api-compat>=0.1.7 ; extra == 'all'
+ - fastparquet>=2022.12.0 ; extra == 'all'
+ - fsspec>=2022.11.0 ; extra == 'all'
+ - gcsfs>=2022.11.0 ; extra == 'all'
+ - html5lib>=1.1 ; extra == 'all'
+ - hypothesis>=6.46.1 ; extra == 'all'
+ - jinja2>=3.1.2 ; extra == 'all'
+ - lxml>=4.9.2 ; extra == 'all'
+ - matplotlib>=3.6.3 ; extra == 'all'
+ - numba>=0.56.4 ; extra == 'all'
+ - numexpr>=2.8.4 ; extra == 'all'
+ - odfpy>=1.4.1 ; extra == 'all'
+ - openpyxl>=3.1.0 ; extra == 'all'
+ - pandas-gbq>=0.19.0 ; extra == 'all'
+ - psycopg2>=2.9.6 ; extra == 'all'
+ - pyarrow>=10.0.1 ; extra == 'all'
+ - pymysql>=1.0.2 ; extra == 'all'
+ - pyqt5>=5.15.9 ; extra == 'all'
+ - pyreadstat>=1.2.0 ; extra == 'all'
+ - pytest>=7.3.2 ; extra == 'all'
+ - pytest-xdist>=2.2.0 ; extra == 'all'
+ - python-calamine>=0.1.7 ; extra == 'all'
+ - pyxlsb>=1.0.10 ; extra == 'all'
+ - qtpy>=2.3.0 ; extra == 'all'
+ - scipy>=1.10.0 ; extra == 'all'
+ - s3fs>=2022.11.0 ; extra == 'all'
+ - sqlalchemy>=2.0.0 ; extra == 'all'
+ - tables>=3.8.0 ; extra == 'all'
+ - tabulate>=0.9.0 ; extra == 'all'
+ - xarray>=2022.12.0 ; extra == 'all'
+ - xlrd>=2.0.1 ; extra == 'all'
+ - xlsxwriter>=3.0.5 ; extra == 'all'
+ - zstandard>=0.19.0 ; extra == 'all'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
name: pandas
version: 2.3.3
@@ -609,6 +1752,70 @@ packages:
- pytest-cov ; extra == 'test'
- scipy ; extra == 'test'
requires_python: '>=3.6'
+- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ name: pillow
+ version: 12.0.0
+ sha256: 0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e
+ requires_dist:
+ - furo ; extra == 'docs'
+ - olefile ; extra == 'docs'
+ - sphinx>=8.2 ; extra == 'docs'
+ - sphinx-autobuild ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - sphinx-inline-tabs ; extra == 'docs'
+ - sphinxext-opengraph ; extra == 'docs'
+ - olefile ; extra == 'fpx'
+ - olefile ; extra == 'mic'
+ - arro3-compute ; extra == 'test-arrow'
+ - arro3-core ; extra == 'test-arrow'
+ - nanoarrow ; extra == 'test-arrow'
+ - pyarrow ; extra == 'test-arrow'
+ - check-manifest ; extra == 'tests'
+ - coverage>=7.4.2 ; extra == 'tests'
+ - defusedxml ; extra == 'tests'
+ - markdown2 ; extra == 'tests'
+ - olefile ; extra == 'tests'
+ - packaging ; extra == 'tests'
+ - pyroma>=5 ; extra == 'tests'
+ - pytest ; extra == 'tests'
+ - pytest-cov ; extra == 'tests'
+ - pytest-timeout ; extra == 'tests'
+ - pytest-xdist ; extra == 'tests'
+ - trove-classifiers>=2024.10.12 ; extra == 'tests'
+ - defusedxml ; extra == 'xmp'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: pillow
+ version: 12.0.0
+ sha256: f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344
+ requires_dist:
+ - furo ; extra == 'docs'
+ - olefile ; extra == 'docs'
+ - sphinx>=8.2 ; extra == 'docs'
+ - sphinx-autobuild ; extra == 'docs'
+ - sphinx-copybutton ; extra == 'docs'
+ - sphinx-inline-tabs ; extra == 'docs'
+ - sphinxext-opengraph ; extra == 'docs'
+ - olefile ; extra == 'fpx'
+ - olefile ; extra == 'mic'
+ - arro3-compute ; extra == 'test-arrow'
+ - arro3-core ; extra == 'test-arrow'
+ - nanoarrow ; extra == 'test-arrow'
+ - pyarrow ; extra == 'test-arrow'
+ - check-manifest ; extra == 'tests'
+ - coverage>=7.4.2 ; extra == 'tests'
+ - defusedxml ; extra == 'tests'
+ - markdown2 ; extra == 'tests'
+ - olefile ; extra == 'tests'
+ - packaging ; extra == 'tests'
+ - pyroma>=5 ; extra == 'tests'
+ - pytest ; extra == 'tests'
+ - pytest-cov ; extra == 'tests'
+ - pytest-timeout ; extra == 'tests'
+ - pytest-xdist ; extra == 'tests'
+ - trove-classifiers>=2024.10.12 ; extra == 'tests'
+ - defusedxml ; extra == 'xmp'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
name: pillow
version: 12.0.0
@@ -641,10 +1848,22 @@ packages:
- trove-classifiers>=2024.10.12 ; extra == 'tests'
- defusedxml ; extra == 'xmp'
requires_python: '>=3.10'
+- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ sha256: 04c64fb78c520e5c396b6e07bc9082735a5cc28175dbe23138201d0a9441800b
+ md5: 1bd2e65c8c7ef24f4639ae6e850dacc2
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/platformdirs?source=hash-mapping
+ size: 23922
+ timestamp: 1764950726246
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: c237680684b4cf004969398069852d16b5c3f766197c0b9e3e7b05223ff56beb
+ sha256: 8592969607c9bcd3c20d4310cdc6d9e39563708c1dfa6e7d88a60826d1a3b063
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -656,6 +1875,16 @@ packages:
- typer>=0.20.0,<0.21
requires_python: '>=3.11,<3.14'
editable: true
+- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
+ name: protobuf
+ version: 6.33.2
+ sha256: 1f8017c48c07ec5859106533b682260ba3d7c5567b1ca1f24297ce03384d1b4f
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
+ name: protobuf
+ version: 6.33.2
+ sha256: b5d3b5625192214066d99b2b605f5783483575656784de223f00a8d00754fc0e
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
name: protobuf
version: 6.33.2
@@ -668,6 +1897,26 @@ packages:
requires_dist:
- colorama>=0.4.6 ; extra == 'windows-terminal'
requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ sha256: ad0bb78785ab385d0afcca4a55e0226d8e6710ebad6450caa552f5fe61c2f6a0
+ md5: 3a830511a81b99b67a1206a9d29b44b3
+ depends:
+ - astroid >=4.0.2,<=4.1.0.dev0
+ - colorama >=0.4.5
+ - isort >=5,<8,!=5.13
+ - mccabe >=0.6,<0.8
+ - platformdirs >=2.2
+ - python >=3.10
+ - tomli >=1.1.0
+ - tomlkit >=0.10.1
+ - dill >=0.3.7
+ - python
+ license: GPL-2.0-or-later
+ license_family: GPL
+ purls:
+ - pkg:pypi/pylint?source=hash-mapping
+ size: 390859
+ timestamp: 1764517517150
- pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
name: pyparsing
version: 3.2.5
@@ -676,6 +1925,59 @@ packages:
- railroad-diagrams ; extra == 'diagrams'
- jinja2 ; extra == 'diagrams'
requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.11-hc97d973_100_cp313.conda
+ build_number: 100
+ sha256: 9cf014cf28e93ee242bacfbf664e8b45ae06e50b04291e640abeaeb0cba0364c
+ md5: 0cbb0010f1d8ecb64a428a8d4214609e
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - bzip2 >=1.0.8,<2.0a0
+ - ld_impl_linux-64 >=2.36.1
+ - libexpat >=2.7.3,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - liblzma >=5.8.1,<6.0a0
+ - libmpdec >=4.0.0,<5.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libuuid >=2.41.2,<3.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - ncurses >=6.5,<7.0a0
+ - openssl >=3.5.4,<4.0a0
+ - python_abi 3.13.* *_cp313
+ - readline >=8.2,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ license: Python-2.0
+ purls: []
+ size: 37226336
+ timestamp: 1765021889577
+ python_site_packages_path: lib/python3.13/site-packages
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.13.11-h4c0d347_100_cp313.conda
+ build_number: 100
+ sha256: bbb0b341c3ce460d02087e1c5e0d3bb814c270f4ae61f82c0e2996ec3902d301
+ md5: a6e2b5b263090516ec36efdd51dcc35b
+ depends:
+ - bzip2 >=1.0.8,<2.0a0
+ - ld_impl_linux-aarch64 >=2.36.1
+ - libexpat >=2.7.3,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - liblzma >=5.8.1,<6.0a0
+ - libmpdec >=4.0.0,<5.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libuuid >=2.41.2,<3.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - ncurses >=6.5,<7.0a0
+ - openssl >=3.5.4,<4.0a0
+ - python_abi 3.13.* *_cp313
+ - readline >=8.2,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ license: Python-2.0
+ purls: []
+ size: 33896215
+ timestamp: 1765020450426
+ python_site_packages_path: lib/python3.13/site-packages
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_100_cp313.conda
build_number: 100
sha256: c476f4e9b6d97c46b496b442878924868a54e5727251549ebfc82027aa52af68
@@ -722,6 +2024,29 @@ packages:
name: pytz
version: '2025.2'
sha256: 5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
+- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
+ sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002
+ md5: d7d95fc8287ea7bf33e0e7116d2b95ec
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 345073
+ timestamp: 1765813471974
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda
+ sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216
+ md5: 3d49cad61f829f4f0e0611547a9cda12
+ depends:
+ - libgcc >=14
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 357597
+ timestamp: 1765815673644
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477
md5: f8381319127120ce51e081dce4865cf4
@@ -753,6 +2078,124 @@ packages:
- markdown-it-py>=2.2.0
- pygments>=2.13.0,<3.0.0
requires_python: '>=3.8.0'
+- pypi: https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ name: scikit-learn
+ version: 1.8.0
+ sha256: 74b66d8689d52ed04c271e1329f0c61635bcaf5b926db9b12d58914cdc01fe57
+ requires_dist:
+ - numpy>=1.24.1
+ - scipy>=1.10.0
+ - joblib>=1.3.0
+ - threadpoolctl>=3.2.0
+ - numpy>=1.24.1 ; extra == 'build'
+ - scipy>=1.10.0 ; extra == 'build'
+ - cython>=3.1.2 ; extra == 'build'
+ - meson-python>=0.17.1 ; extra == 'build'
+ - numpy>=1.24.1 ; extra == 'install'
+ - scipy>=1.10.0 ; extra == 'install'
+ - joblib>=1.3.0 ; extra == 'install'
+ - threadpoolctl>=3.2.0 ; extra == 'install'
+ - matplotlib>=3.6.1 ; extra == 'benchmark'
+ - pandas>=1.5.0 ; extra == 'benchmark'
+ - memory-profiler>=0.57.0 ; extra == 'benchmark'
+ - matplotlib>=3.6.1 ; extra == 'docs'
+ - scikit-image>=0.22.0 ; extra == 'docs'
+ - pandas>=1.5.0 ; extra == 'docs'
+ - seaborn>=0.13.0 ; extra == 'docs'
+ - memory-profiler>=0.57.0 ; extra == 'docs'
+ - sphinx>=7.3.7 ; extra == 'docs'
+ - sphinx-copybutton>=0.5.2 ; extra == 'docs'
+ - sphinx-gallery>=0.17.1 ; extra == 'docs'
+ - numpydoc>=1.2.0 ; extra == 'docs'
+ - pillow>=10.1.0 ; extra == 'docs'
+ - pooch>=1.8.0 ; extra == 'docs'
+ - sphinx-prompt>=1.4.0 ; extra == 'docs'
+ - sphinxext-opengraph>=0.9.1 ; extra == 'docs'
+ - plotly>=5.18.0 ; extra == 'docs'
+ - polars>=0.20.30 ; extra == 'docs'
+ - sphinx-design>=0.6.0 ; extra == 'docs'
+ - sphinxcontrib-sass>=0.3.4 ; extra == 'docs'
+ - pydata-sphinx-theme>=0.15.3 ; extra == 'docs'
+ - sphinx-remove-toctrees>=1.0.0.post1 ; extra == 'docs'
+ - towncrier>=24.8.0 ; extra == 'docs'
+ - matplotlib>=3.6.1 ; extra == 'examples'
+ - scikit-image>=0.22.0 ; extra == 'examples'
+ - pandas>=1.5.0 ; extra == 'examples'
+ - seaborn>=0.13.0 ; extra == 'examples'
+ - pooch>=1.8.0 ; extra == 'examples'
+ - plotly>=5.18.0 ; extra == 'examples'
+ - matplotlib>=3.6.1 ; extra == 'tests'
+ - pandas>=1.5.0 ; extra == 'tests'
+ - pytest>=7.1.2 ; extra == 'tests'
+ - pytest-cov>=2.9.0 ; extra == 'tests'
+ - ruff>=0.11.7 ; extra == 'tests'
+ - mypy>=1.15 ; extra == 'tests'
+ - pyamg>=5.0.0 ; extra == 'tests'
+ - polars>=0.20.30 ; extra == 'tests'
+ - pyarrow>=12.0.0 ; extra == 'tests'
+ - numpydoc>=1.2.0 ; extra == 'tests'
+ - pooch>=1.8.0 ; extra == 'tests'
+ - conda-lock==3.0.1 ; extra == 'maintenance'
+ requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: scikit-learn
+ version: 1.8.0
+ sha256: 8fdf95767f989b0cfedb85f7ed8ca215d4be728031f56ff5a519ee1e3276dc2e
+ requires_dist:
+ - numpy>=1.24.1
+ - scipy>=1.10.0
+ - joblib>=1.3.0
+ - threadpoolctl>=3.2.0
+ - numpy>=1.24.1 ; extra == 'build'
+ - scipy>=1.10.0 ; extra == 'build'
+ - cython>=3.1.2 ; extra == 'build'
+ - meson-python>=0.17.1 ; extra == 'build'
+ - numpy>=1.24.1 ; extra == 'install'
+ - scipy>=1.10.0 ; extra == 'install'
+ - joblib>=1.3.0 ; extra == 'install'
+ - threadpoolctl>=3.2.0 ; extra == 'install'
+ - matplotlib>=3.6.1 ; extra == 'benchmark'
+ - pandas>=1.5.0 ; extra == 'benchmark'
+ - memory-profiler>=0.57.0 ; extra == 'benchmark'
+ - matplotlib>=3.6.1 ; extra == 'docs'
+ - scikit-image>=0.22.0 ; extra == 'docs'
+ - pandas>=1.5.0 ; extra == 'docs'
+ - seaborn>=0.13.0 ; extra == 'docs'
+ - memory-profiler>=0.57.0 ; extra == 'docs'
+ - sphinx>=7.3.7 ; extra == 'docs'
+ - sphinx-copybutton>=0.5.2 ; extra == 'docs'
+ - sphinx-gallery>=0.17.1 ; extra == 'docs'
+ - numpydoc>=1.2.0 ; extra == 'docs'
+ - pillow>=10.1.0 ; extra == 'docs'
+ - pooch>=1.8.0 ; extra == 'docs'
+ - sphinx-prompt>=1.4.0 ; extra == 'docs'
+ - sphinxext-opengraph>=0.9.1 ; extra == 'docs'
+ - plotly>=5.18.0 ; extra == 'docs'
+ - polars>=0.20.30 ; extra == 'docs'
+ - sphinx-design>=0.6.0 ; extra == 'docs'
+ - sphinxcontrib-sass>=0.3.4 ; extra == 'docs'
+ - pydata-sphinx-theme>=0.15.3 ; extra == 'docs'
+ - sphinx-remove-toctrees>=1.0.0.post1 ; extra == 'docs'
+ - towncrier>=24.8.0 ; extra == 'docs'
+ - matplotlib>=3.6.1 ; extra == 'examples'
+ - scikit-image>=0.22.0 ; extra == 'examples'
+ - pandas>=1.5.0 ; extra == 'examples'
+ - seaborn>=0.13.0 ; extra == 'examples'
+ - pooch>=1.8.0 ; extra == 'examples'
+ - plotly>=5.18.0 ; extra == 'examples'
+ - matplotlib>=3.6.1 ; extra == 'tests'
+ - pandas>=1.5.0 ; extra == 'tests'
+ - pytest>=7.1.2 ; extra == 'tests'
+ - pytest-cov>=2.9.0 ; extra == 'tests'
+ - ruff>=0.11.7 ; extra == 'tests'
+ - mypy>=1.15 ; extra == 'tests'
+ - pyamg>=5.0.0 ; extra == 'tests'
+ - polars>=0.20.30 ; extra == 'tests'
+ - pyarrow>=12.0.0 ; extra == 'tests'
+ - numpydoc>=1.2.0 ; extra == 'tests'
+ - pooch>=1.8.0 ; extra == 'tests'
+ - conda-lock==3.0.1 ; extra == 'maintenance'
+ requires_python: '>=3.11'
- pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
name: scikit-learn
version: 1.8.0
@@ -812,6 +2255,50 @@ packages:
- pooch>=1.8.0 ; extra == 'tests'
- conda-lock==3.0.1 ; extra == 'maintenance'
requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ name: scipy
+ version: 1.16.3
+ sha256: 7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88
+ requires_dist:
+ - numpy>=1.25.2,<2.6
+ - 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'
+ - 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'
+ - mypy==1.10.0 ; extra == 'dev'
+ - typing-extensions ; extra == 'dev'
+ - types-psutil ; extra == 'dev'
+ - pycodestyle ; extra == 'dev'
+ - ruff>=0.0.292 ; extra == 'dev'
+ - cython-lint>=0.12.2 ; extra == 'dev'
+ - rich-click ; extra == 'dev'
+ - doit>=0.36.0 ; extra == 'dev'
+ - pydevtool ; extra == 'dev'
+ requires_python: '>=3.11'
- pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl
name: scipy
version: 1.16.3
@@ -856,6 +2343,50 @@ packages:
- doit>=0.36.0 ; extra == 'dev'
- pydevtool ; extra == 'dev'
requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
+ name: scipy
+ version: 1.16.3
+ sha256: 0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959
+ requires_dist:
+ - numpy>=1.25.2,<2.6
+ - 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'
+ - 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'
+ - mypy==1.10.0 ; extra == 'dev'
+ - typing-extensions ; extra == 'dev'
+ - types-psutil ; extra == 'dev'
+ - pycodestyle ; extra == 'dev'
+ - ruff>=0.0.292 ; extra == 'dev'
+ - cython-lint>=0.12.2 ; extra == 'dev'
+ - rich-click ; extra == 'dev'
+ - doit>=0.36.0 ; extra == 'dev'
+ - pydevtool ; extra == 'dev'
+ requires_python: '>=3.11'
- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
name: setuptools
version: 80.9.0
@@ -923,6 +2454,40 @@ packages:
version: 1.17.0
sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: statsmodels
+ version: 0.14.6
+ sha256: 730f3297b26749b216a06e4327fe0be59b8d05f7d594fb6caff4287b69654589
+ requires_dist:
+ - numpy>=1.22.3,<3
+ - scipy>=1.8,!=1.9.2
+ - pandas>=1.4,!=2.1.0
+ - patsy>=0.5.6
+ - packaging>=21.3
+ - cython>=3.0.10 ; extra == 'build'
+ - cython>=3.0.10 ; extra == 'develop'
+ - cython>=3.0.10,<4 ; extra == 'develop'
+ - setuptools-scm[toml]~=8.0 ; extra == 'develop'
+ - matplotlib>=3 ; extra == 'develop'
+ - colorama ; extra == 'develop'
+ - joblib ; extra == 'develop'
+ - jinja2 ; extra == 'develop'
+ - pytest>=7.3.0,<8 ; extra == 'develop'
+ - pytest-randomly ; extra == 'develop'
+ - pytest-xdist ; extra == 'develop'
+ - pytest-cov ; extra == 'develop'
+ - pywinpty ; os_name == 'nt' and extra == 'develop'
+ - flake8 ; extra == 'develop'
+ - isort ; extra == 'develop'
+ - sphinx ; extra == 'docs'
+ - nbconvert ; extra == 'docs'
+ - jupyter-client ; extra == 'docs'
+ - ipykernel ; extra == 'docs'
+ - matplotlib ; extra == 'docs'
+ - nbformat ; extra == 'docs'
+ - numpydoc ; extra == 'docs'
+ - pandas-datareader ; extra == 'docs'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
name: statsmodels
version: 0.14.6
@@ -957,6 +2522,40 @@ packages:
- numpydoc ; extra == 'docs'
- pandas-datareader ; extra == 'docs'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: statsmodels
+ version: 0.14.6
+ sha256: 89ee7d595f5939cc20bf946faedcb5137d975f03ae080f300ebb4398f16a5bd4
+ requires_dist:
+ - numpy>=1.22.3,<3
+ - scipy>=1.8,!=1.9.2
+ - pandas>=1.4,!=2.1.0
+ - patsy>=0.5.6
+ - packaging>=21.3
+ - cython>=3.0.10 ; extra == 'build'
+ - cython>=3.0.10 ; extra == 'develop'
+ - cython>=3.0.10,<4 ; extra == 'develop'
+ - setuptools-scm[toml]~=8.0 ; extra == 'develop'
+ - matplotlib>=3 ; extra == 'develop'
+ - colorama ; extra == 'develop'
+ - joblib ; extra == 'develop'
+ - jinja2 ; extra == 'develop'
+ - pytest>=7.3.0,<8 ; extra == 'develop'
+ - pytest-randomly ; extra == 'develop'
+ - pytest-xdist ; extra == 'develop'
+ - pytest-cov ; extra == 'develop'
+ - pywinpty ; os_name == 'nt' and extra == 'develop'
+ - flake8 ; extra == 'develop'
+ - isort ; extra == 'develop'
+ - sphinx ; extra == 'docs'
+ - nbconvert ; extra == 'docs'
+ - jupyter-client ; extra == 'docs'
+ - ipykernel ; extra == 'docs'
+ - matplotlib ; extra == 'docs'
+ - nbformat ; extra == 'docs'
+ - numpydoc ; extra == 'docs'
+ - pandas-datareader ; extra == 'docs'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
name: tensorboard
version: 2.20.0
@@ -1019,6 +2618,88 @@ packages:
- tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
- tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ name: tensorflow
+ version: 2.20.0
+ sha256: 5fa3729b0126f75a99882b89fb7d536515721eda8014a63e259e780ba0a37372
+ requires_dist:
+ - absl-py>=1.0.0
+ - astunparse>=1.6.0
+ - flatbuffers>=24.3.25
+ - gast>=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
+ - google-pasta>=0.1.1
+ - libclang>=13.0.0
+ - opt-einsum>=2.3.2
+ - packaging
+ - protobuf>=5.28.0
+ - requests>=2.21.0,<3
+ - setuptools
+ - six>=1.12.0
+ - termcolor>=1.1.0
+ - typing-extensions>=3.6.6
+ - wrapt>=1.11.0
+ - grpcio>=1.24.3,<2.0
+ - tensorboard~=2.20.0
+ - keras>=3.10.0
+ - numpy>=1.26.0
+ - h5py>=3.11.0
+ - ml-dtypes>=0.5.1,<1.0.0
+ - nvidia-cublas-cu12>=12.5.3.2,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-cupti-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-nvcc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-nvrtc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-runtime-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cudnn-cu12>=9.3.0.75,<10.0 ; extra == 'and-cuda'
+ - nvidia-cufft-cu12>=11.2.3.61,<12.0 ; extra == 'and-cuda'
+ - nvidia-curand-cu12>=10.3.6.82,<11.0 ; extra == 'and-cuda'
+ - nvidia-cusolver-cu12>=11.6.3.83,<12.0 ; extra == 'and-cuda'
+ - nvidia-cusparse-cu12>=12.5.1.3,<13.0 ; extra == 'and-cuda'
+ - nvidia-nccl-cu12>=2.25.1,<3.0 ; extra == 'and-cuda'
+ - nvidia-nvjitlink-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
+ - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ name: tensorflow
+ version: 2.20.0
+ sha256: 47c88e05a07f1ead4977b4894b3ecd4d8075c40191065afc4fd9355c9db3d926
+ requires_dist:
+ - absl-py>=1.0.0
+ - astunparse>=1.6.0
+ - flatbuffers>=24.3.25
+ - gast>=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
+ - google-pasta>=0.1.1
+ - libclang>=13.0.0
+ - opt-einsum>=2.3.2
+ - packaging
+ - protobuf>=5.28.0
+ - requests>=2.21.0,<3
+ - setuptools
+ - six>=1.12.0
+ - termcolor>=1.1.0
+ - typing-extensions>=3.6.6
+ - wrapt>=1.11.0
+ - grpcio>=1.24.3,<2.0
+ - tensorboard~=2.20.0
+ - keras>=3.10.0
+ - numpy>=1.26.0
+ - h5py>=3.11.0
+ - ml-dtypes>=0.5.1,<1.0.0
+ - nvidia-cublas-cu12>=12.5.3.2,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-cupti-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-nvcc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-nvrtc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cuda-runtime-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - nvidia-cudnn-cu12>=9.3.0.75,<10.0 ; extra == 'and-cuda'
+ - nvidia-cufft-cu12>=11.2.3.61,<12.0 ; extra == 'and-cuda'
+ - nvidia-curand-cu12>=10.3.6.82,<11.0 ; extra == 'and-cuda'
+ - nvidia-cusolver-cu12>=11.6.3.83,<12.0 ; extra == 'and-cuda'
+ - nvidia-cusparse-cu12>=12.5.1.3,<13.0 ; extra == 'and-cuda'
+ - nvidia-nccl-cu12>=2.25.1,<3.0 ; extra == 'and-cuda'
+ - nvidia-nvjitlink-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
+ - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
+ - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
name: termcolor
version: 3.2.0
@@ -1032,6 +2713,33 @@ packages:
version: 3.6.0
sha256: 43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb
requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda
+ sha256: 1544760538a40bcd8ace2b1d8ebe3eb5807ac268641f8acdc18c69c5ebfeaf64
+ md5: 86bc20552bf46075e3d92b67f089172d
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - xorg-libx11 >=1.8.12,<2.0a0
+ license: TCL
+ license_family: BSD
+ purls: []
+ size: 3284905
+ timestamp: 1763054914403
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h561c983_103.conda
+ sha256: 154e73f6269f92ad5257aa2039278b083998fd19d371e150f307483fb93c07ae
+ md5: 631db4799bc2bfe4daccf80bb3cbc433
+ depends:
+ - libgcc >=13
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - xorg-libx11 >=1.8.12,<2.0a0
+ license: TCL
+ license_family: BSD
+ purls: []
+ size: 3333495
+ timestamp: 1763059192223
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
sha256: ad0c67cb03c163a109820dc9ecf77faf6ec7150e942d1e8bb13e5d39dc058ab7
md5: a73d54a5abba6543cb2f0af1bfbd6851
@@ -1043,6 +2751,29 @@ packages:
purls: []
size: 3125484
timestamp: 1763055028377
+- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
+ sha256: cb77c660b646c00a48ef942a9e1721ee46e90230c7c570cdeb5a893b5cce9bff
+ md5: d2732eb636c264dc9aa4cbee404b1a53
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/tomli?source=compressed-mapping
+ size: 20973
+ timestamp: 1760014679845
+- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ sha256: f8d3b49c084831a20923f66826f30ecfc55a4cd951e544b7213c692887343222
+ md5: 146402bf0f11cbeb8f781fa4309a95d3
+ depends:
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/tomlkit?source=hash-mapping
+ size: 38777
+ timestamp: 1749127286558
- pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
name: typer
version: 0.20.0
@@ -1097,6 +2828,22 @@ packages:
- pytest>=6.0.0 ; extra == 'test'
- setuptools>=65 ; extra == 'test'
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: wrapt
+ version: 2.0.1
+ sha256: c654eafb01afac55246053d67a4b9a984a3567c3808bb7df2f8de1c1caba2e1c
+ requires_dist:
+ - pytest ; extra == 'dev'
+ - setuptools ; extra == 'dev'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+ name: wrapt
+ version: 2.0.1
+ sha256: c8d60527d1ecfc131426b10d93ab5d53e08a09c5fa0175f6b21b3252080c70a9
+ requires_dist:
+ - pytest ; extra == 'dev'
+ - setuptools ; extra == 'dev'
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
name: wrapt
version: 2.0.1
@@ -1105,3 +2852,36 @@ packages:
- pytest ; extra == 'dev'
- setuptools ; extra == 'dev'
requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
+ sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae
+ md5: 30cd29cb87d819caead4d55184c1d115
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/zipp?source=compressed-mapping
+ size: 24194
+ timestamp: 1764460141901
+- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
+ sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7
+ md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 601375
+ timestamp: 1764777111296
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda
+ sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75
+ md5: c3655f82dcea2aa179b291e7099c1fcc
+ depends:
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 614429
+ timestamp: 1764777145593
diff --git a/pyproject.toml b/pyproject.toml
index 2c50668..e58749f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -43,3 +43,6 @@ platforms = ["osx-arm64","linux-64","linux-aarch64"]
PREFACE = { path = ".", editable = true }
[tool.pixi.tasks]
+
+[tool.pixi.dependencies]
+pylint = ">=4.0.4,<5"
diff --git a/src/preface/__init__.py b/src/preface/__init__.py
index b459070..1d28c88 100644
--- a/src/preface/__init__.py
+++ b/src/preface/__init__.py
@@ -1 +1,5 @@
+"""
+PREFACE package initialization.
+"""
+
__version__ = "1.0.0dev"
diff --git a/src/preface/predict.py b/src/preface/predict.py
index 8c0e6d3..951ee81 100644
--- a/src/preface/predict.py
+++ b/src/preface/predict.py
@@ -1,12 +1,18 @@
+"""
+Predict module for PREFACE.
+"""
+# pylint: disable=too-many-locals,too-many-branches,too-many-statements
-import typer
-import joblib
import os
import json
from typing import Optional, Union
+import numpy as np
import pandas as pd
+import joblib
+import typer
from sklearn.linear_model import LinearRegression
+from tensorflow import keras # pylint: disable=no-name-in-module,import-error
def preface_predict(
@@ -45,8 +51,9 @@ def preface_predict(
is_olm = model_data["is_olm"]
the_intercept = model_data["the_intercept"]
the_slope = model_data["the_slope"]
- the_intercept_X = model_data["the_intercept_X"]
- the_slope_X = model_data["the_slope_X"]
+ # Variable names in the pickle are fixed, but we map them to snake_case locals
+ intercept_x = model_data["the_intercept_X"]
+ slope_x = model_data["the_slope_X"]
dir_path = os.path.dirname(meta_path)
model: Union[LinearRegression, keras.Model]
@@ -64,7 +71,7 @@ def preface_predict(
else:
x_ratio = float(np.nan)
- FFX: float = (x_ratio - the_intercept_X) / the_slope_X
+ ffx: float = (x_ratio - intercept_x) / slope_x
bin_table["feat_id"] = (
bin_table["chr"].astype(str)
@@ -90,14 +97,14 @@ def preface_predict(
prediction = the_intercept + the_slope * prediction
- json_dict = {"FFX": FFX / 100, "PREFACE": prediction / 100}
+ json_dict = {"FFX": ffx / 100, "PREFACE": prediction / 100}
if json_output:
- if json_output != "stdout" and json_output != "":
- with open(json_output, "w") as f:
+ if json_output not in ("stdout", ""):
+ with open(json_output, "w", encoding="utf-8") as f:
json.dump(json_dict, f)
else:
typer.echo(json.dumps(json_dict))
else:
- typer.echo(f"FFX = {FFX:.4g}%")
+ typer.echo(f"FFX = {ffx:.4g}%")
typer.echo(f"PREFACE = {prediction:.4g}%")
diff --git a/src/preface/preface.py b/src/preface/preface.py
index 8ff2e0e..1b2a1f2 100644
--- a/src/preface/preface.py
+++ b/src/preface/preface.py
@@ -1,3 +1,7 @@
+"""
+PREFACE CLI entry point.
+"""
+
import typer
from preface.predict import preface_predict
diff --git a/src/preface/train.py b/src/preface/train.py
index 91e0e70..834a9f0 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -1,9 +1,11 @@
-#!/usr/bin/env python3
+"""
+Training module for PREFACE.
+"""
import os
import time
-import json
from typing import List, Optional, Any, Dict, Union
+from pathlib import Path
import numpy as np
import pandas as pd
@@ -13,13 +15,11 @@
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from joblib import Parallel, delayed
-import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import typer
-
# Constants
EXCLUDE_CHRS: List[str] = ['13', '18', '21', 'X', 'Y']
COLOR_A: str = '#8DD1C6'
@@ -27,50 +27,68 @@
COLOR_C: str = '#C87878'
-
-def get_m_diff(v1: np.ndarray, v2: np.ndarray, abs_val: bool = True) -> float:
+def get_mean_diff(v1: np.ndarray, v2: np.ndarray, abs_val: bool = True) -> float:
+ """Calculate mean difference."""
if not abs_val:
return float(np.mean(v1 - v2))
return float(np.mean(np.abs(v1 - v2)))
-def get_sd_diff(v1: np.ndarray, v2: np.ndarray) -> float:
- return float(np.std(np.abs(v1 - v2), ddof=1)) # ddof=1 for sample sd
+
+def get_std_diff(v1: np.ndarray, v2: np.ndarray) -> float:
+ """Calculate standard deviation of difference."""
+ return float(np.std(np.abs(v1 - v2), ddof=1)) # ddof=1 for sample sd
+
def plot_performance(
- v1: np.ndarray,
- v2: np.ndarray,
- pca_explained_variance_ratio: np.ndarray,
- n_feat: int,
- xlab: str,
- ylab: str,
+ v1: np.ndarray,
+ v2: np.ndarray,
+ pca_explained_variance_ratio: np.ndarray,
+ n_feat: int,
+ xlab: str,
+ ylab: str,
path: str
) -> List[float]:
-
+ """Plot performance metrics."""
+
# R plot layout: 1 row, 3 columns.
-
- fig, axes = plt.subplots(1, 3, figsize=(15, 5))
-
+ _, axes = plt.subplots(1, 3, figsize=(15, 5))
+
# Plot 1: PCA Importance
ax = axes[0]
y_vals = pca_explained_variance_ratio
x_vals = np.arange(1, len(y_vals) + 1)
-
+
# Filtering zeros for log
mask = y_vals > 0
x_vals = x_vals[mask]
y_vals = y_vals[mask]
-
+
ax.plot(np.log(x_vals), np.log(y_vals), color=COLOR_A, linewidth=2)
ax.set_xlabel('Principal components (log scale)')
ax.set_ylabel('Proportion of variance (log scale)')
ax.set_title('PCA')
-
+
# Vertical line at n_feat
log_n_feat = np.log(n_feat)
ylim = ax.get_ylim()
- ax.vlines(log_n_feat, ylim[0], ylim[1] * 0.99, colors=COLOR_C, linestyles='dotted', linewidth=3)
- ax.text(log_n_feat, ylim[1], 'Number of features', color=COLOR_C, ha='center', va='bottom', fontsize=8)
-
+ ax.vlines(
+ log_n_feat,
+ ylim[0],
+ ylim[1] * 0.99,
+ colors=COLOR_C,
+ linestyles='dotted',
+ linewidth=3
+ )
+ ax.text(
+ log_n_feat,
+ ylim[1],
+ 'Number of features',
+ color=COLOR_C,
+ ha='center',
+ va='bottom',
+ fontsize=8
+ )
+
# Plot 2: Scatter Plot
ax = axes[1]
mx = max(float(np.max(v1)), float(np.max(v2)))
@@ -80,12 +98,12 @@ def plot_performance(
ax.set_xlim(0, mx)
ax.set_ylim(0, mx)
ax.set_title('Scatter plot')
-
+
# OLS fit
intercept: float = 0.0
slope: float = 0.0
correlation: float = 0.0
-
+
if len(np.unique(v1)) > 1:
reg = LinearRegression().fit(v1.reshape(-1, 1), v2)
fit_line = reg.predict(np.array([[0], [mx]]))
@@ -96,82 +114,85 @@ def plot_performance(
else:
# Fallback if v1 is constant
mean_v2 = float(np.mean(v2))
- ax.plot([0, mx], [mean_v2, mean_v2], color=COLOR_A, linestyle='--', linewidth=2, label='Mean fit')
+ ax.plot(
+ [0, mx],
+ [mean_v2, mean_v2],
+ color=COLOR_A,
+ linestyle='--',
+ linewidth=2,
+ label='Mean fit'
+ )
intercept = mean_v2
slope = 0.0
correlation = 0.0
# Identity line
ax.plot([0, mx], [0, mx], color=COLOR_B, linestyle=':', linewidth=3, label='f(x)=x')
-
+
ax.legend()
ax.text(0, mx * 1.03, f'(r = {correlation:.3g})', fontsize=9, ha='left')
-
+
# Plot 3: Histogram of errors
ax = axes[2]
errors = v1 - v2
n_bins = max(20, len(v1)//10)
- counts, bins, patches = ax.hist(errors, bins=n_bins, density=True, color='black', alpha=0.5)
+ counts, bins, _ = ax.hist(errors, bins=n_bins, density=True, color='black', alpha=0.5)
ax.set_xlabel(f'{xlab} - {ylab}')
ax.set_ylabel('Density')
ax.set_title('Histogram')
-
+
mx_hist = float(np.max(counts)) if len(counts) > 0 else 0.1
# Mean error line
- mean_err = get_m_diff(v1, v2, abs_val=False)
- ax.vlines(mean_err, 0, mx_hist, colors=COLOR_A, linestyles='--', linewidth=3, label='mean error')
+ mean_err = get_mean_diff(v1, v2, abs_val=False)
+ ax.vlines(
+ mean_err, 0, mx_hist, colors=COLOR_A, linestyles='--', linewidth=3, label='mean error'
+ )
ax.vlines(0, 0, mx_hist, colors=COLOR_B, linestyles=':', linewidth=3, label='x=0')
ax.legend()
-
- mae = get_m_diff(v1, v2)
- sd_diff = get_sd_diff(v1, v2)
+
+ mae = get_mean_diff(v1, v2)
+ sd_diff = get_std_diff(v1, v2)
min_bin = float(min(bins)) if len(bins) > 0 else 0.0
- ax.text(min_bin, mx_hist * 1.03, f'(MAE = {mae:.3g} ± {sd_diff:.3g})', fontsize=9, ha='left')
-
+ ax.text(
+ min_bin,
+ mx_hist * 1.03,
+ f'(MAE = {mae:.3g} ± {sd_diff:.3g})',
+ fontsize=9,
+ ha='left'
+ )
+
plt.tight_layout()
plt.savefig(path, dpi=300)
plt.close()
-
+
return [intercept, slope, mae, sd_diff, correlation]
-def load_bed_file(filepath: str) -> Optional[np.ndarray]:
- try:
- # Assuming BED has header
- df = pd.read_csv(filepath, sep='\t')
- # Check columns
- if 'ratio' not in df.columns:
- # Fallback if no header
- pass
-
- df = df[df['chr'] != 'Y']
- return df['ratio'].values
- except Exception as e:
- print(f"Error reading {filepath}: {e}")
- return None
-
-def load_bed_full(filepath: str) -> pd.DataFrame:
- # For creating the full training frame with coordinates
- df = pd.read_csv(filepath, sep='\t')
- return df
-
-def train_neural_network(X_train: np.ndarray, Y_train: np.ndarray, hidden_units: int) -> keras.Model:
+
+def train_neural_network(
+ x_train: np.ndarray, y_train: np.ndarray, hidden_units: int
+) -> keras.Model:
+ """Train a simple neural network."""
model = keras.Sequential([
- layers.Input(shape=(X_train.shape[1],)),
+ layers.Input(shape=(x_train.shape[1],)),
layers.Dense(hidden_units, activation='sigmoid'),
layers.Dense(1, activation='linear')
])
-
+
model.compile(optimizer='adam', loss='mse')
-
- early_stop = keras.callbacks.EarlyStopping(monitor='loss', patience=10, restore_best_weights=True)
-
- model.fit(X_train, Y_train, epochs=200, batch_size=32, verbose=0, callbacks=[early_stop])
+
+ early_stop = keras.callbacks.EarlyStopping(
+ monitor='loss', patience=10, restore_best_weights=True
+ )
+
+ model.fit(
+ x_train, y_train, epochs=200, batch_size=32, verbose=0, callbacks=[early_stop]
+ )
return model
def preface_train(
- config_file: str = typer.Option(..., "--config", help="Path to config file"),
- out_dir: str = typer.Option(..., "--outdir", help="Output directory"),
+ config_file: Path = typer.Option(..., "--config", help="Path to config file"),
+ out_dir: Path = typer.Option(..., "--outdir", help="Output directory"),
n_feat: int = typer.Option(50, "--nfeat", help="Number of features (PCA components)"),
hidden: int = typer.Option(2, "--hidden", help="Hidden units in NN"),
cpus: int = typer.Option(1, "--cpus", help="Number of CPUs"),
@@ -183,272 +204,291 @@ def preface_train(
Train the PREFACE model.
"""
start_time = time.time()
-
- if not os.path.exists(config_file):
- typer.echo(f"The file '{config_file}' does not exist.")
- raise typer.Exit(code=1)
-
- if not os.path.exists(out_dir):
- os.makedirs(out_dir, exist_ok=True)
-
- skewcorrect: bool = not noskewcorrect
- train_gender: List[str] = ['M']
- if femprop:
- train_gender = ['M', 'F']
-
+ train_sex: List[str] = ['M', 'F'] if femprop else ['M']
+
out_dir_path: str = os.path.join(out_dir, '')
-
+
# Load config
- config = pd.read_csv(config_file, sep='\t', comment='#', dtype={'gender': str, 'ID': str})
-
+ config = pd.read_csv(
+ config_file, sep='\t', comment='#', dtype={'sex': str, 'ID': str}
+ )
+
# Check samples
- labeled_samples = config[config['gender'].isin(train_gender)]
+ labeled_samples = config[config['sex'].isin(train_sex)]
if len(labeled_samples) < n_feat:
typer.echo(f"Please provide at least {n_feat} labeled samples.")
raise typer.Exit(code=1)
-
- # Shuffle
- config = config.sample(frac=1, random_state=1).reset_index(drop=True)
-
+
# Load first file for structure
first_path: str = str(config['filepath'].iloc[0])
training_frame_meta = load_bed_full(first_path)
training_frame_meta = training_frame_meta[['chr', 'start', 'end']]
-
+
# Load all ratios in parallel
typer.echo("Loading samples...")
- results: List[Optional[np.ndarray]] = Parallel(n_jobs=cpus)(delayed(load_bed_file)(str(f)) for f in config['filepath'])
-
+ results: List[pd.DataFrame] = Parallel(n_jobs=cpus)(
+ delayed(pd.read_csv)(str(f), sep='\t') for f in config['filepath']
+ )
+
lengths: List[int] = [len(x) for x in results if x is not None]
if len(set(lengths)) > 1:
typer.echo("Error: Input BED files have different numbers of bins (excluding Y).")
raise typer.Exit(code=1)
-
+
# Filter out Nones and stack
valid_results: List[np.ndarray] = [res for res in results if res is not None]
training_frame_sub = np.column_stack(valid_results)
-
+
# Ensure meta alignment
training_frame_meta = training_frame_meta[training_frame_meta['chr'] != 'Y']
if len(training_frame_meta) != training_frame_sub.shape[0]:
typer.echo("Mismatch in row counts between metadata and loaded data.")
raise typer.Exit(code=1)
-
+
is_x = training_frame_meta['chr'] == 'X'
x_ratios_raw = training_frame_sub[is_x, :]
x_ratios = 2 ** np.nanmean(x_ratios_raw, axis=0)
-
+
typer.echo("Creating training frame...")
-
+
mask_keep = ~training_frame_meta['chr'].isin(EXCLUDE_CHRS)
-
+
training_frame_filtered = training_frame_sub[mask_keep, :]
training_frame_meta_filtered = training_frame_meta[mask_keep]
-
+
# Transpose: Samples as rows, Features as columns
training_frame = training_frame_filtered.T
-
- feature_names = (training_frame_meta_filtered['chr'].astype(str) + ':' +
- training_frame_meta_filtered['start'].astype(str) + '-' +
- training_frame_meta_filtered['end'].astype(str)).values
-
+
+ feature_names = (
+ training_frame_meta_filtered['chr'].astype(str) + ':' +
+ training_frame_meta_filtered['start'].astype(str) + '-' +
+ training_frame_meta_filtered['end'].astype(str)
+ ).values
+
training_df = pd.DataFrame(training_frame, columns=feature_names)
-
+
# Filter NAs
na_threshold = len(config) * 0.01
cols_to_keep = training_df.isna().sum() < na_threshold
training_df = training_df.loc[:, cols_to_keep]
-
+
possible_features = training_df.columns.values
mean_features = training_df.mean()
-
+
training_df = training_df.fillna(mean_features)
-
+
typer.echo(f"Remaining training features after 'NA' filtering: {len(possible_features)}")
-
+
os.makedirs(os.path.join(out_dir_path, 'training_repeats'), exist_ok=True)
-
+
repeats: int = 10
test_percentage: float = 1.0 / repeats
-
- train_mask = config['gender'].isin(train_gender)
+
+ train_mask = config['sex'].isin(train_sex)
train_indices_all: List[int] = config.index[train_mask].tolist()
-
+
n_train_samples: int = len(train_indices_all)
test_number: int = int(n_train_samples * test_percentage)
-
+
max_feat: int = n_train_samples - test_number - 1
if n_feat > max_feat:
typer.echo(f"Too few samples were provided for --nfeat {n_feat}, using --nfeat {max_feat}")
n_feat = max_feat
-
+
train_subset_df = training_df.iloc[train_indices_all].reset_index(drop=True)
y_all: np.ndarray = config.loc[train_indices_all, 'FF'].astype(float).values
-
+
results_repeats: List[Dict[str, Any]] = []
-
+
for i in range(1, repeats + 1):
typer.echo(f"Model training | Repeat {i}/{repeats} ...")
-
+
start_idx: int = int((i - 1) * test_number)
end_idx: int = int(i * test_number)
-
+
test_idxs_local: List[int] = list(range(start_idx, end_idx))
train_idxs_local: List[int] = list(set(range(len(train_subset_df))) - set(test_idxs_local))
-
- X_tr_local = train_subset_df.iloc[train_idxs_local]
- X_te_local = train_subset_df.iloc[test_idxs_local]
- Y_tr_local = y_all[train_idxs_local]
- Y_te_local = y_all[test_idxs_local]
-
+
+ x_tr_local = train_subset_df.iloc[train_idxs_local]
+ x_te_local = train_subset_df.iloc[test_idxs_local]
+ y_tr_local = y_all[train_idxs_local]
+ y_te_local = y_all[test_idxs_local]
+
typer.echo("\tExecuting principal component analysis ...")
- n_components_pca: int = min(n_feat * 10, len(X_tr_local) - 1)
+ n_components_pca: int = min(n_feat * 10, len(x_tr_local) - 1)
pca = PCA(n_components=n_components_pca)
- pca.fit(X_tr_local)
-
- X_train_pca = pca.transform(X_tr_local)
- X_test_pca = pca.transform(X_te_local)
-
- X_train_model = X_train_pca[:, :n_feat]
- X_test_model = X_test_pca[:, :n_feat]
-
+ pca.fit(x_tr_local)
+
+ x_train_pca = pca.transform(x_tr_local)
+ x_test_pca = pca.transform(x_te_local)
+
+ x_train_model = x_train_pca[:, :n_feat]
+ x_test_model = x_test_pca[:, :n_feat]
+
prediction: Optional[np.ndarray] = None
if olm:
typer.echo("\tTraining ordinary linear model ...")
model = LinearRegression()
- model.fit(X_train_model, Y_tr_local)
- prediction = model.predict(X_test_model)
+ model.fit(x_train_model, y_tr_local)
+ prediction = model.predict(x_test_model)
else:
typer.echo("\tTraining neural network ...")
- model = train_neural_network(X_train_model, Y_tr_local, hidden)
- prediction = model.predict(X_test_model).flatten()
-
- info = plot_performance(prediction, Y_te_local, pca.explained_variance_ratio_, n_feat,
- 'PREFACE (%)', 'FF (%)', os.path.join(out_dir_path, 'training_repeats', f'repeat_{i}.png'))
-
+ model = train_neural_network(x_train_model, y_tr_local, hidden)
+ prediction = model.predict(x_test_model).flatten()
+
+ info = plot_performance(
+ prediction,
+ y_te_local,
+ pca.explained_variance_ratio_,
+ n_feat,
+ 'PREFACE (%)',
+ 'FF (%)',
+ os.path.join(out_dir_path, 'training_repeats', f'repeat_{i}.png')
+ )
+
results_repeats.append({
'intercept': info[0],
'slope': info[1],
'prediction': prediction
})
-
+
predictions: np.ndarray = np.concatenate([r['prediction'] for r in results_repeats])
-
+
the_intercept: float = 0.0
the_slope: float = 1.0
-
+
n_used: int = int(test_number * repeats)
y_used: np.ndarray = y_all[:n_used]
-
- if skewcorrect:
+
+ if not noskewcorrect:
np.random.seed(1)
n_pred: int = len(predictions)
p: np.ndarray = np.random.choice(n_pred, max(1, n_pred // 4), replace=False)
-
+
pred_p = predictions[p]
y_p = y_used[p]
-
+
reg_skew = LinearRegression().fit(pred_p.reshape(-1, 1), y_p)
the_intercept = float(reg_skew.intercept_)
the_slope = float(reg_skew.coef_[0])
-
+
typer.echo("Correction for skew:")
typer.echo(f"\tIntercept: {the_intercept}")
typer.echo(f"\tSlope: {the_slope}")
typer.echo("Training FFX Model...")
-
- mask_m = config['gender'] == 'M'
+
+ mask_m = config['sex'] == 'M'
v1_m: np.ndarray = config.loc[mask_m, 'FF'].astype(float).values
v2_m: np.ndarray = x_ratios[mask_m]
-
- X_rlm = sm.add_constant(v1_m)
- rlm_model = sm.RLM(v2_m, X_rlm, M=sm.robust.norms.HuberT())
+
+ x_rlm = sm.add_constant(v1_m)
+ rlm_model = sm.RLM(v2_m, x_rlm, M=sm.robust.norms.HuberT())
rlm_results = rlm_model.fit()
-
+
fit_params = rlm_results.params
- the_intercept_X: float = fit_params[0]
- the_slope_X: float = fit_params[1]
-
- fig, axes = plt.subplots(1, 2, figsize=(10, 5))
+ intercept_x: float = fit_params[0]
+ slope_x: float = fit_params[1]
+
+ _, axes = plt.subplots(1, 2, figsize=(10, 5))
ax = axes[0]
ax.scatter(v1_m, v2_m, s=10, c='black', alpha=0.6)
ax.set_xlabel('FF (%)')
ax.set_ylabel('μ(ratio X)')
mx = max(v1_m) if len(v1_m) > 0 else 1
ax.set_xlim(0, mx)
-
- x_range = np.array([min(v1_m) if len(v1_m)>0 else 0, max(v1_m) if len(v1_m)>0 else 1])
- y_range = the_intercept_X + the_slope_X * x_range
+
+ x_range = np.array(
+ [min(v1_m) if len(v1_m) > 0 else 0, max(v1_m) if len(v1_m) > 0 else 1]
+ )
+ y_range = intercept_x + slope_x * x_range
ax.plot(x_range, y_range, color=COLOR_A, linestyle='--', linewidth=2, label='RLS fit')
ax.legend()
-
+
ax = axes[1]
- v2_corrected = (v2_m - the_intercept_X) / the_slope_X if the_slope_X != 0 else v2_m
+ v2_corrected = (v2_m - intercept_x) / slope_x if slope_x != 0 else v2_m
ax.scatter(v1_m, v2_corrected, s=10, c='black', alpha=0.6)
ax.set_xlabel('FF (%)')
ax.set_ylabel('FFX (%)')
ax.set_xlim(0, mx)
- ax.plot([x_range[0], x_range[1]], [x_range[0], x_range[1]], color=COLOR_B, linestyle=':', linewidth=3)
-
+ ax.plot(
+ [x_range[0], x_range[1]], [x_range[0], x_range[1]],
+ color=COLOR_B, linestyle=':', linewidth=3
+ )
+
plt.tight_layout()
plt.savefig(os.path.join(out_dir_path, 'FFX.png'), dpi=300)
plt.close()
-
+
predictions_corrected = the_intercept + the_slope * predictions
-
+
typer.echo("Executing final principal component analysis ...")
-
+
pca_final = PCA(n_components=min(n_feat * 10, len(train_subset_df) - 1))
pca_final.fit(train_subset_df)
-
- X_train_final = pca_final.transform(train_subset_df)[:, :n_feat]
- Y_train_final = y_all
-
+
+ x_train_final = pca_final.transform(train_subset_df)[:, :n_feat]
+ y_train_final = y_all
+
model_final: Union[LinearRegression, keras.Model]
if olm:
typer.echo("Training final ordinary linear model ...")
model_final = LinearRegression()
- model_final.fit(X_train_final, Y_train_final)
+ model_final.fit(x_train_final, y_train_final)
else:
typer.echo("Training final neural network ...")
- model_final = train_neural_network(X_train_final, Y_train_final, hidden)
-
- info_overall = plot_performance(predictions_corrected, y_used, pca_final.explained_variance_ratio_,
- n_feat, 'PREFACE (%)', 'FF (%)', os.path.join(out_dir_path, 'overall_performance.png'))
-
+ model_final = train_neural_network(x_train_final, y_train_final, hidden)
+
+ info_overall = plot_performance(
+ predictions_corrected,
+ y_used,
+ pca_final.explained_variance_ratio_,
+ n_feat,
+ 'PREFACE (%)',
+ 'FF (%)',
+ os.path.join(out_dir_path, 'overall_performance.png')
+ )
+
deviations = np.abs(predictions_corrected - y_used)
mae = info_overall[2]
sd = info_overall[3]
outlier_threshold = mae + 3 * sd
outlier_indices = np.where(deviations > outlier_threshold)[0]
-
- with open(os.path.join(out_dir_path, 'training_statistics.txt'), 'w') as f:
+
+ with open(
+ os.path.join(out_dir_path, 'training_statistics.txt'), 'w', encoding='utf-8'
+ ) as f:
f.write('PREFACE - PREdict FetAl ComponEnt\n\n')
-
+
if len(outlier_indices) > 0:
f.write('Below, some of the top candidates for outlier removal are listed.\n')
f.write('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- _\n')
f.write('ID\tFF (%) - PREFACE (%)\n')
-
+
sorted_outlier_idxs = outlier_indices[np.argsort(-deviations[outlier_indices])]
subset_ids = config.loc[train_indices_all, 'ID'].values[:n_used]
- subset_diffs = (predictions_corrected - y_used)
-
+ subset_diffs = predictions_corrected - y_used
+
for idx in sorted_outlier_idxs:
f.write(f"{subset_ids[idx]}\t{subset_diffs[idx]:.4f}\n")
f.write('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- _\n\n')
-
+
elapsed_time = time.time() - start_time
f.write(f"Training time: {elapsed_time:.0f} seconds\n")
f.write(f"Overall correlation (r): {info_overall[4]:.4f}\n")
- f.write(f"Overall mean absolute error (MAE): {info_overall[2]:.4f} ± {info_overall[3]:.4f}\n")
-
+ f.write(
+ f"Overall mean absolute error (MAE): "
+ f"{info_overall[2]:.4f} ± {info_overall[3]:.4f}\n"
+ )
+
mask_10 = y_used < 10.0
if np.any(mask_10):
devs_10 = deviations[mask_10]
- f.write(f"FF < 10% mean absolute error (MAE): {np.mean(devs_10):.4f} ± {np.std(devs_10, ddof=1):.4f}\n")
-
+ f.write(
+ f"FF < 10% mean absolute error (MAE): "
+ f"{np.mean(devs_10):.4f} ± {np.std(devs_10, ddof=1):.4f}\n"
+ )
+
f.write("Correction for skew: \n")
f.write(f"\tIntercept: {the_intercept}\n")
f.write(f"\tSlope: {the_slope}\n\n")
@@ -461,16 +501,18 @@ def preface_train(
'is_olm': olm,
'the_intercept': the_intercept,
'the_slope': the_slope,
- 'the_intercept_X': the_intercept_X,
- 'the_slope_X': the_slope_X,
+ 'the_intercept_X': intercept_x,
+ 'the_slope_X': slope_x,
}
-
+
joblib.dump(model_data, os.path.join(out_dir_path, 'model_meta.pkl'))
-
+
if olm:
joblib.dump(model_final, os.path.join(out_dir_path, 'model_weights.pkl'))
else:
model_final.save(os.path.join(out_dir_path, 'model_weights.keras'))
-
- typer.echo(f"Finished! Consult '{out_dir_path}training_statistics.txt' to analyse your model's performance.")
+ typer.echo(
+ f"Finished! Consult '{out_dir_path}training_statistics.txt' "
+ "to analyse your model's performance."
+ )
diff --git a/src/preface/utils/ffy.py b/src/preface/utils/ffy.py
index 35893a9..1710e63 100644
--- a/src/preface/utils/ffy.py
+++ b/src/preface/utils/ffy.py
@@ -1,2 +1,37 @@
-def ffy():
- pass
\ No newline at end of file
+"""
+FFY calculation utility.
+"""
+
+from pathlib import Path
+import numpy as np
+import typer
+
+
+def wisecondorx_ffy(
+ wisecondorx_npz: Path = typer.Argument(
+ ..., help="Path to WisecondorX NPZ file", exists=True, file_okay=True, dir_okay=False
+ ),
+ sex_cutoff: float = typer.Option(0.2, "--sex-cutoff", help="Cutoff for sex determination"),
+) -> dict:
+ """
+ Calculate fetal fraction from Y chromosome (FFY) using WisecondorX output.
+ """
+ npz = np.load(wisecondorx_npz, encoding="latin1", allow_pickle=True)
+ read_counts = npz["sample"].item()
+ # Calculate read depth from autosomes (1-22) + X (23) + Y (24)?
+ # The original code did range(1, 25) which is 1..24.
+ # Usually 23 is X, 24 is Y.
+ read_depth = float(
+ np.sum([np.sum(read_counts[x]) for x in [str(y) for y in range(1, 25)]])
+ )
+ y_chr_fraction = np.array(read_counts["24"], dtype="float") / read_depth
+
+ ffy_val = np.sum(y_chr_fraction)
+
+ sex = "unknown"
+ if ffy_val > sex_cutoff:
+ sex = "male"
+ else:
+ sex = "female"
+
+ return {"FFY": ffy_val, "sex": sex}
diff --git a/src/preface/utils/npz_to_parquet.py b/src/preface/utils/npz_to_parquet.py
index df687d3..5d0b17c 100644
--- a/src/preface/utils/npz_to_parquet.py
+++ b/src/preface/utils/npz_to_parquet.py
@@ -1,5 +1,10 @@
+"""
+Convert NPZ to Parquet utility.
+"""
+
+# pylint: disable=broad-exception-caught
+
import os
-import sys
from typing import List
import numpy as np
@@ -29,7 +34,8 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
output_filepath = os.path.join(output_dir, output_filename)
typer.echo(
- f" Converting array '{key}' (shape: {array.shape}, dtype: {array.dtype}) to {output_filepath}"
+ f" Converting array '{key}' (shape: {array.shape}, "
+ f"dtype: {array.dtype}) to {output_filepath}"
)
# Handle different array dimensions
@@ -48,7 +54,8 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
)
elif array.ndim > 2:
typer.echo(
- f" Warning: Array '{key}' has {array.ndim} dimensions. Flattening for Parquet storage.",
+ f" Warning: Array '{key}' has {array.ndim} dimensions. "
+ "Flattening for Parquet storage.",
err=True,
)
# Flatten to 1D and then treat as a single-column DataFrame
@@ -82,4 +89,4 @@ def npz_to_parquet(
if __name__ == "__main__":
- typer.run(npz_to_parquet)
\ No newline at end of file
+ typer.run(npz_to_parquet)
From 29a897406dd30f23a53ded4366496e487c9bc295 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 26 Dec 2025 22:38:55 +0100
Subject: [PATCH 07/50] fix training
---
.gitignore | 1 +
PREFACE.R | 161 --------
pixi.lock | 226 ++++++++++--
pyproject.toml | 3 +-
src/preface/lib/functions.py | 325 +++++++++++++++++
src/preface/lib/schemas.py | 21 ++
src/preface/predict.py | 2 -
src/preface/preface.py | 9 +-
src/preface/train.py | 689 ++++++++++++-----------------------
9 files changed, 766 insertions(+), 671 deletions(-)
create mode 100644 src/preface/lib/schemas.py
diff --git a/.gitignore b/.gitignore
index 4427018..6609d58 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
data/
*.egg-info
__pycache__/
+.gemini/
# pixi environments
.pixi/*
!.pixi/config.toml
diff --git a/PREFACE.R b/PREFACE.R
index b0a5cda..4530a70 100755
--- a/PREFACE.R
+++ b/PREFACE.R
@@ -1,130 +1,3 @@
-#!/usr/bin/env Rscript
-
-version = 'v0.1.2'
-
-# ---
-# Functions
-# ---
-
-print.help <- function(w = 'all'){
- cat('\nUsage:\n')
- if (w == 'all' | w == 'train'){
- cat('\tRScript PREFACE.R train --config path/to/config.txt --outdir path/to/dir/ [--nfeat (int) --hidden (int) --cpus (int) --femprop --olm --noskewcorrect]\n')
- }
- if (w == 'all' | w == 'predict'){
- cat('\tRScript PREFACE.R predict --infile path/to/infile.bed --model path/to/model.RData [–-json]\n')
- }
- cat('\n')
- quit(save = 'no')
-}
-
-unrec.args <- function(w = 'all'){
- cat('\nUnrecongized arguments, have you read the manual at \'https://github.com/CenterForMedicalGeneticsGhent/PREFACE\'?')
- print.help(w)
-}
-
-parse.op.arg <- function(args, sub.arg, default){
- if (sub.arg %in% args){
- i = which(args == sub.arg) + 1
- resp = as.integer(args[i])
- args = args[-i]
- } else {
- resp = default
- }
- if (is.na(resp)){
- cat(paste0('Argument \'', sub.arg, '\' requires a value.\n'))
- print.help()
- }
- return(list(resp, args))
-}
-
-get.m.diff <- function(v1, v2, abs = T){
- if (!abs){
- return(mean(v1 - v2))
- }
- return(mean(abs(v1 - v2)))
-}
-
-get.sd.diff <- function(v1, v2){
- return(sd(abs(v1 - v2)))
-}
-
-plot.performance <- function(v1, v2, summary, n.feat, xlab, ylab, path){
-
- png(path, width=7.6, height=2.65, units='in', res=1024)
- par(mar=c(3,1,2,1), mgp=c(1.6, 0.2, 0.2), mfrow=c(1,3), xpd = NA, oma=c(0,3,0,0))
-
- ylim = c(min(summary$importance[2,][summary$importance[2,] != 0]), max(summary$importance[2,]))
- xlim = c(1, ncol(summary$importance))
-
- plot(log(1:ncol(summary$importance)), log(summary$importance[2,]), ylim = log(ylim), xlim = log(xlim), type = 'l', lwd = 2,
- axes = F, ylab = 'Proportion of variance', xlab = 'Principal components', col = color.A, main = 'PCA')
-
- segments(log(n.feat), log(ylim[1]), log(n.feat), log(ylim[2] * .99), lwd = 3, lty = 3, c = color.C)
- text(log(n.feat), log(ylim[2]), 'Number of features', col = color.C, adj = 0.5, cex = 0.8)
-
- label.seq = round(seq(from = xlim[1], to = xlim[2], (xlim[2] - xlim[1])/xlim[2]))
- axis(1, tcl=0.5, at = log(label.seq), labels = label.seq)
- label.seq = seq(from = ylim[1], to = ylim[2], (ylim[2] - ylim[1])/xlim[2])
- axis(2, tcl=0.5, at = log(label.seq), labels = rep('', length(label.seq)), las = 2)
- axis(2, tcl=0.5, at = log(c(label.seq[1], label.seq[length(label.seq)])), labels = c(label.seq[1], label.seq[length(label.seq)]), las = 2)
-
- xlim <- c(0, max(v1))
- ylim <- c(0, max(v2))
- mx <- max(xlim[2], ylim[2])
-
- plot(v1, v2, pch = 16, cex = 0.6, axes = F, xlab = xlab, ylab = ylab,
- xlim = c(0, mx), ylim = c(0, mx),
- main = 'Scatter plot')
-
- legend('topleft', c('OLS fit', 'f(x)=x'), bty = 'n',
- col = c(color.A, color.B), cex = 0.9, text.col = c(color.A, color.B), text.font = 2)
-
- axis(1, tcl=0.5)
- axis(2, tcl=0.5, las = 2)
-
- fit <- coef(lsfit(v1, v2))
-
- par(xpd=F)
- segments(0, 0, mx, mx, lwd = 3, lty = 3, c = color.B)
- segments(0, fit[1], mx, fit[1] + mx * fit[2], lwd = 3, lty = 2, c = color.A)
- par(xpd=NA)
-
- text(0, mx * 1.03,
- paste0('(r = ', signif(cor(v1, v2), 3), ')'),
- cex = 0.9, adj = 0)
- t = hist(v1-v2, max(20,length(v1)/10), axes = F, xlab = paste0(xlab, ' - ', ylab),
- main = 'Histogram', ylab = 'Density', c = 'black')
-
- mx = max(t$counts)
- segments(0, 0, 0, mx, lwd = 3, lty = 3, c = color.B)
- segments(get.m.diff(v1, v2, abs = F), 0, get.m.diff(v1, v2, abs = F), mx, lwd = 3, lty = 2, c = color.A)
- axis(1, tcl=0.5)
- axis(2, tcl=0.5, las = 2)
- legend('topleft', c('mean error', 'x=0'), bty = 'n',
- col = c(color.A, color.B), cex = 0.9, text.col = c(color.A, color.B), text.font = 2)
-
- text(min(t$breaks), mx * 1.03,
- paste0('(MAE = ', signif(get.m.diff(v1, v2), 3), ' ± ', signif(get.sd.diff(v1, v2), 3), ')'),
- cex = 0.9, adj = 0)
-
- dev.off()
- return(c(fit[1], fit[2], get.m.diff(v1, v2), get.sd.diff(v1, v2), cor(v1, v2)))
-}
-
-train.neural <- function(f, train.nn, hidden){
- tryCatch({
- return(neuralnet(f, train.nn, hidden = hidden, stepmax = 1e6))
- }, warning = function(e) {
- cat(paste0('Neural network did not converge. Re-run and decrease --hidden or optimize --nfeat. Alternatively, use --olm.\n'))
- quit(save = 'no')
- })
-}
-
-# ---
-# Modules
-# ---
-
train <- function(args){
start.time <- proc.time()
@@ -495,37 +368,3 @@ predict <- function(args){
}
}
}
-
-# ---
-# overall lib
-# ---
-
-suppressMessages(library('data.table'))
-suppressMessages(library('glmnet'))
-suppressMessages(library('neuralnet'))
-
-# ---
-# param
-# ---
-
-exclude.chrs <- c('13', '18', '21', 'X', 'Y')
-
-color.A = rgb(141, 209, 198, maxColorValue = 255)
-color.B = rgb(227, 200, 138, maxColorValue = 255)
-color.C = rgb(200, 120, 120, maxColorValue = 255)
-
-# ---
-# Main
-# ---
-
-set.seed(1)
-args <- commandArgs(trailingOnly = TRUE)
-if ('--help' %in% args | '--h' %in% args) print.help()
-if ('--version' %in% args | '--v' %in% args){cat(paste0(version), '\n') ; quit(save = 'no')}
-if (length(args) == 0) unrec.args()
-if (!(args[1] %in% c('train', 'predict'))){
- unrec.args()
-}
-if (args[1] == 'train') train(args[-1])
-
-if (args[1] == 'predict') predict(args[-1])
diff --git a/pixi.lock b/pixi.lock
index e907434..63382ce 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -43,13 +43,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
@@ -57,7 +58,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
@@ -66,17 +67,21 @@ environments:
- pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/10/ca162f45a102738958dcec8023062dad0cbc17d1ab99d68c4e4a6c45fb2b/numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
@@ -92,8 +97,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
@@ -134,13 +142,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
@@ -148,7 +157,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
@@ -157,17 +166,21 @@ environments:
- pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/95/03/dc0723a013c7d7c19de5ef29e932c3081df1c14ba582b8b86b5de9db7f0f/numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
@@ -183,8 +196,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
@@ -219,13 +235,14 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
@@ -233,7 +250,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
@@ -242,17 +259,21 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
@@ -268,8 +289,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
@@ -316,6 +340,13 @@ packages:
version: 2.3.1
sha256: eeecf07f0c2a93ace0772c92e596ace6d3d3996c042b2128459aaae2a76de11d
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
+ name: annotated-types
+ version: 0.7.0
+ sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53
+ requires_dist:
+ - typing-extensions>=4.0.0 ; python_full_version < '3.9'
+ requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py313h78bf25f_0.conda
sha256: dc26da204d67948118207322b563a010720497f14dd4b7b0a385bf69a73016ad
md5: 65899d37680aab12f5e33ad07d15d1fd
@@ -539,10 +570,10 @@ packages:
- pkg:pypi/dill?source=hash-mapping
size: 94889
timestamp: 1764517905571
-- pypi: https://files.pythonhosted.org/packages/ee/1b/00a78aa2e8fbd63f9af08c9c19e6deb3d5d66b4dda677a0f61654680ee89/flatbuffers-25.9.23-py2.py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
name: flatbuffers
- version: 25.9.23
- sha256: 255538574d6cb6d0a79a17ec8bc0d30985913b87513a01cce8bcdb6b4c44d0e2
+ version: 25.12.19
+ sha256: 7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4
- pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
name: fonttools
version: 4.61.1
@@ -741,10 +772,10 @@ packages:
version: 1.5.3
sha256: 5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ba/61/cc8be27bd65082440754be443b17b6f7c185dec5e00dfdaeab4f8662e4a8/keras-3.12.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
name: keras
- version: 3.12.0
- sha256: 02b69e007d5df8042286c3bcc2a888539e3e487590ffb08f6be1b4354df50aa8
+ version: 3.13.0
+ sha256: 096793e2be6230816f3f7e030370e66c0f4a89707c59bf2d8fad3ca33869bd1c
requires_dist:
- absl-py
- numpy
@@ -754,7 +785,7 @@ packages:
- optree
- ml-dtypes
- packaging
- requires_python: '>=3.10'
+ requires_python: '>=3.11'
- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
name: kiwisolver
version: 1.4.9
@@ -1258,6 +1289,11 @@ packages:
- pylint>=2.6.0 ; extra == 'dev'
- pyink ; extra == 'dev'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
+ name: mypy-extensions
+ version: 1.1.0
+ sha256: 1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
name: namex
version: 0.1.0
@@ -1290,20 +1326,20 @@ packages:
purls: []
size: 797030
timestamp: 1738196177597
-- pypi: https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
name: numpy
- version: 2.3.5
- sha256: aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188
+ version: 2.4.0
+ sha256: f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/95/03/dc0723a013c7d7c19de5ef29e932c3081df1c14ba582b8b86b5de9db7f0f/numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+- pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
name: numpy
- version: 2.3.5
- sha256: 9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d
+ version: 2.4.0
+ sha256: 8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a
requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/f5/10/ca162f45a102738958dcec8023062dad0cbc17d1ab99d68c4e4a6c45fb2b/numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
name: numpy
- version: 2.3.5
- sha256: 11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017
+ version: 2.4.0
+ sha256: 39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d
requires_python: '>=3.11'
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d
@@ -1742,6 +1778,60 @@ packages:
- xlsxwriter>=3.0.5 ; extra == 'all'
- zstandard>=0.19.0 ; extra == 'all'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
+ name: pandera
+ version: 0.27.1
+ sha256: 944838f134035bbc548410943be662379669488e00f3d290ff2c36b6df52665e
+ requires_dist:
+ - packaging>=20.0
+ - pydantic
+ - typeguard
+ - typing-extensions
+ - typing-inspect>=0.6.0
+ - numpy>=1.24.4 ; extra == 'pandas'
+ - pandas>=2.1.1 ; extra == 'pandas'
+ - hypothesis>=6.92.7 ; extra == 'strategies'
+ - scipy ; extra == 'hypotheses'
+ - pyyaml>=5.1 ; extra == 'io'
+ - black ; extra == 'io'
+ - frictionless<=4.40.8 ; extra == 'io'
+ - pandas-stubs ; extra == 'mypy'
+ - scipy-stubs ; python_full_version >= '3.10' and extra == 'mypy'
+ - fastapi ; extra == 'fastapi'
+ - geopandas<1.1.0 ; extra == 'geopandas'
+ - shapely ; extra == 'geopandas'
+ - pyspark[connect]>=3.2.0,<4.0.0 ; extra == 'pyspark'
+ - modin ; extra == 'modin'
+ - ray ; extra == 'modin'
+ - dask[dataframe] ; extra == 'modin'
+ - distributed ; extra == 'modin'
+ - modin ; extra == 'modin-ray'
+ - ray ; extra == 'modin-ray'
+ - modin ; extra == 'modin-dask'
+ - dask[dataframe] ; extra == 'modin-dask'
+ - distributed ; extra == 'modin-dask'
+ - dask[dataframe] ; extra == 'dask'
+ - distributed ; extra == 'dask'
+ - ibis-framework>=9.0.0 ; extra == 'ibis'
+ - polars>=0.20.0 ; extra == 'polars'
+ - hypothesis>=6.92.7 ; extra == 'all'
+ - scipy ; extra == 'all'
+ - scipy-stubs ; python_full_version >= '3.10' and extra == 'all'
+ - pyyaml>=5.1 ; extra == 'all'
+ - black ; extra == 'all'
+ - frictionless<=4.40.8 ; extra == 'all'
+ - pyspark[connect]>=3.2.0,<4.0.0 ; extra == 'all'
+ - modin ; extra == 'all'
+ - ray ; extra == 'all'
+ - dask[dataframe] ; extra == 'all'
+ - distributed ; extra == 'all'
+ - pandas-stubs ; extra == 'all'
+ - fastapi ; extra == 'all'
+ - geopandas<1.1.0 ; extra == 'all'
+ - shapely ; extra == 'all'
+ - ibis-framework>=9.0.0 ; extra == 'all'
+ - polars>=0.20.0 ; extra == 'all'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
name: patsy
version: 1.0.2
@@ -1863,18 +1953,18 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: 8592969607c9bcd3c20d4310cdc6d9e39563708c1dfa6e7d88a60826d1a3b063
+ sha256: 8a47fcd7ffd33684027ee0a0a4c2eba532cf0181786f9e88a029e2dc1bf83b06
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
- - scikit-learn>=1.8.0,<2
+ - scikit-learn==1.8.0
- tensorflow>=2.20.0,<3
- matplotlib>=3.10.8,<4
- joblib>=1.5.3,<2
- statsmodels>=0.14.6,<0.15
- typer>=0.20.0,<0.21
+ - pandera>=0.27.1,<0.28
requires_python: '>=3.11,<3.14'
- editable: true
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
version: 6.33.2
@@ -1890,6 +1980,39 @@ packages:
version: 6.33.2
sha256: d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
+ name: pydantic
+ version: 2.12.5
+ sha256: e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d
+ requires_dist:
+ - annotated-types>=0.6.0
+ - pydantic-core==2.41.5
+ - typing-extensions>=4.14.1
+ - typing-inspection>=0.4.2
+ - email-validator>=2.0.0 ; extra == 'email'
+ - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ name: pydantic-core
+ version: 2.41.5
+ sha256: 0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0
+ requires_dist:
+ - typing-extensions>=4.14.1
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl
+ name: pydantic-core
+ version: 2.41.5
+ sha256: 112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34
+ requires_dist:
+ - typing-extensions>=4.14.1
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ name: pydantic-core
+ version: 2.41.5
+ sha256: 406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586
+ requires_dist:
+ - typing-extensions>=4.14.1
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
name: pygments
version: 2.19.2
@@ -1917,10 +2040,10 @@ packages:
- pkg:pypi/pylint?source=hash-mapping
size: 390859
timestamp: 1764517517150
-- pypi: https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
name: pyparsing
- version: 3.2.5
- sha256: e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e
+ version: 3.3.1
+ sha256: 023b5e7e5520ad96642e2c6db4cb683d3970bd640cdf7115049a6e9c3682df82
requires_dist:
- railroad-diagrams ; extra == 'diagrams'
- jinja2 ; extra == 'diagrams'
@@ -2774,10 +2897,18 @@ packages:
- pkg:pypi/tomlkit?source=hash-mapping
size: 38777
timestamp: 1749127286558
-- pypi: https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
+ name: typeguard
+ version: 4.4.4
+ sha256: b5f562281b6bfa1f5492470464730ef001646128b180769880468bd84b68b09e
+ requires_dist:
+ - importlib-metadata>=3.6 ; python_full_version < '3.10'
+ - typing-extensions>=4.14.0
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
name: typer
- version: 0.20.0
- sha256: 5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a
+ version: 0.20.1
+ sha256: 4b3bde918a67c8e03d861aa02deca90a95bbac572e71b1b9be56ff49affdb5a8
requires_dist:
- click>=8.0.0
- typing-extensions>=3.7.4.3
@@ -2789,6 +2920,21 @@ packages:
version: 4.15.0
sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
+ name: typing-inspect
+ version: 0.9.0
+ sha256: 9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f
+ requires_dist:
+ - mypy-extensions>=0.3.0
+ - typing-extensions>=3.7.4
+ - typing>=3.7.4 ; python_full_version < '3.5'
+- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
+ name: typing-inspection
+ version: 0.4.2
+ sha256: 4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7
+ requires_dist:
+ - typing-extensions>=4.12.0
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
name: tzdata
version: '2025.3'
diff --git a/pyproject.toml b/pyproject.toml
index e58749f..45ccd2b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,12 +14,13 @@ classifiers = [
dependencies = [
"pandas>=2.3.3,<3",
"numpy>=2.3.5,<3",
- "scikit-learn>=1.8.0,<2",
+ "scikit-learn==1.8.0",
"tensorflow>=2.20.0,<3",
"matplotlib>=3.10.8,<4",
"joblib>=1.5.3,<2",
"statsmodels>=0.14.6,<0.15",
"typer>=0.20.0,<0.21",
+ "pandera>=0.27.1,<0.28",
]
[build-system]
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index e69de29..1f50a1f 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -0,0 +1,325 @@
+from pathlib import Path
+
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+from sklearn.decomposition import PCA
+import statsmodels.api as sm
+from sklearn.linear_model import LinearRegression
+from sklearn.metrics import mean_absolute_error
+import tensorflow as tf
+from tensorflow.keras import ( # pylint: disable=no-name-in-module,import-error # type: ignore
+ Model,
+ layers,
+)
+
+COLOR_A: str = "#8DD1C6"
+COLOR_B: str = "#E3C88A"
+COLOR_C: str = "#C87878"
+
+
+def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.DataFrame:
+ """Preprocess ratios DataFrame by excluding chromosomes, adding region column and transposing.
+ returns a x by 1 dataframe with regions as columns.
+ """
+
+ # santize chr column
+ ratios_df["chr"] = ratios_df["chr"].astype(str).str.replace("chr", "", regex=False)
+ # exclude chromosomes
+ masked_ratios = ratios_df[~ratios_df["chr"].isin(exclude_chrs)]
+ # add region column
+ masked_ratios["region"] = (
+ f"{masked_ratios['chr']}:{masked_ratios['start']}-{masked_ratios['end']}"
+ )
+ # drop chr, start, end columns
+ masked_ratios = masked_ratios.drop(columns=["chr", "start", "end"])
+ # set region as index
+ masked_ratios = masked_ratios.set_index("region")
+ # transpose to have regions as columns
+ masked_ratios = masked_ratios.T
+
+ return masked_ratios
+
+
+def build_multi_output_nn(input_dim: int, n_neurons: int):
+ """Build a multi-output neural network for regression and classification."""
+ inputs = layers.Input(shape=(input_dim,))
+ x = layers.Dense(n_neurons, activation="relu")(inputs)
+ x = layers.Dense(n_neurons // 2, activation="relu")(x)
+ # Head 1: Regression
+ reg_out = layers.Dense(1, activation="linear", name="reg_output")(x)
+
+ # Head 2: Classification
+ class_out = layers.Dense(1, activation="sigmoid", name="class_output")(x)
+
+ nn = Model(inputs=inputs, outputs=[reg_out, class_out])
+ nn.compile(
+ optimizer="adam",
+ loss={"reg_output": "mse", "class_output": "binary_crossentropy"},
+ loss_weights={"reg_output": 1.0, "class_output": 1.0},
+ )
+ return nn
+
+
+class PCALayer(layers.Layer):
+ def __init__(self, pca, **kwargs):
+ super(
+ PCALayer,
+ self,
+ ).__init__(**kwargs)
+ # Convert Scikit-Learn attributes to TensorFlow constants
+ self.components = tf.constant(pca.components_.T, dtype=tf.float32)
+
+ def call(self, inputs):
+ # PCA: Matrix multiplication with components
+ pca_data = tf.matmul(inputs, self.components)
+ return pca_data
+
+
+def build_ensemble(n_feat: int, pca: PCA, models: list[Model]) -> Model:
+ """
+ Build an ensemble model that averages predictions from multiple fold models.
+ Each fold model is assumed to have two outputs: regression and classification.
+ """
+ # Add input layer
+ ensemble_input = layers.Input(shape=(n_feat,), name="input")
+
+ # Add PCA layer
+ pca_feat = PCALayer(pca, name="pca")(ensemble_input)
+
+ # Add each fold model as a sub-network
+ reg_outputs = []
+ class_outputs = []
+
+ for i, fold_model in enumerate(models):
+ fold_model._name = f"fold_model_{i}" # Ensure unique names
+
+ # Pass the PCA features through the fold model
+ reg_out, class_out = fold_model(pca_feat)
+ reg_outputs.append(reg_out)
+ class_outputs.append(class_out)
+
+ # Average regression outputs
+ avg_reg_output = layers.Average(name="ff_pred")(reg_outputs)
+ avg_class_output = layers.Average(name="sex_pred")(class_outputs)
+
+ # Build and return ensemble model
+ return Model(
+ inputs=ensemble_input, outputs=[avg_reg_output, avg_class_output], name="PREFACE_model"
+ )
+
+
+def plot_regression_performance(
+ y_pred: np.ndarray,
+ y_true: np.ndarray,
+ pca_explained_variance_ratio: np.ndarray,
+ n_feat: int,
+ xlab: str,
+ ylab: str,
+ path: Path,
+) -> dict[str, float]:
+ """
+ Plot performance metrics and return statistics.
+ """
+ # Ensure 1D arrays
+ y_true = np.ravel(y_true)
+ y_pred = np.ravel(y_pred)
+
+ # Calculate metrics
+ mae = mean_absolute_error(y_true, y_pred)
+ diff = y_pred - y_true
+ sd_diff = float(np.std(diff, ddof=1))
+
+ # Linear Regression and Correlation
+ if len(np.unique(y_pred)) > 1:
+ # Use sklearn LinearRegression
+ reg = LinearRegression().fit(y_pred.reshape(-1, 1), y_true)
+ intercept = float(reg.intercept_)
+ slope = float(reg.coef_[0])
+ correlation = float(np.corrcoef(y_true, y_pred)[0, 1])
+ else:
+ intercept = float(np.mean(y_true))
+ slope = 0.0
+ correlation = 0.0
+
+ # Plotting
+ _, axes = plt.subplots(1, 3, figsize=(15, 5))
+
+ # Plot 1: PCA Importance
+ ax = axes[0]
+ y_vals = pca_explained_variance_ratio
+ x_vals = np.arange(1, len(y_vals) + 1)
+
+ # Filter zeros for log scale
+ mask = y_vals > 0
+ ax.plot(np.log(x_vals[mask]), np.log(y_vals[mask]), color=COLOR_A, linewidth=2)
+ ax.set_xlabel("Principal components (log scale)")
+ ax.set_ylabel("Proportion of variance (log scale)")
+ ax.set_title("PCA")
+
+ # Vertical line at n_feat
+ log_n_feat = np.log(n_feat)
+ ylim = ax.get_ylim()
+ ax.vlines(
+ log_n_feat,
+ ylim[0],
+ ylim[1] * 0.99,
+ colors=COLOR_C,
+ linestyles="dotted",
+ linewidth=3,
+ )
+ ax.text(
+ log_n_feat,
+ ylim[1],
+ "Number of features",
+ color=COLOR_C,
+ ha="center",
+ va="bottom",
+ fontsize=8,
+ )
+
+ # Plot 2: Scatter Plot
+ ax = axes[1]
+ mx = max(float(np.max(y_true)), float(np.max(y_pred)))
+ ax.scatter(y_pred, y_true, s=10, c="black", alpha=0.6)
+ ax.set_xlabel(xlab)
+ ax.set_ylabel(ylab)
+ ax.set_xlim(0, mx)
+ ax.set_ylim(0, mx)
+ ax.set_title("Scatter plot")
+
+ # Fit line
+ if slope != 0:
+ fit_line = intercept + slope * np.array([0, mx])
+ ax.plot(
+ [0, mx],
+ fit_line,
+ color=COLOR_A,
+ linestyle="--",
+ linewidth=2,
+ label="OLS fit",
+ )
+ else:
+ ax.plot(
+ [0, mx],
+ [intercept, intercept],
+ color=COLOR_A,
+ linestyle="--",
+ linewidth=2,
+ label="Mean fit",
+ )
+
+ # Identity line
+ ax.plot([0, mx], [0, mx], color=COLOR_B, linestyle=":", linewidth=3, label="f(x)=x")
+ ax.legend()
+ ax.text(0, mx * 1.03, f"(r = {correlation:.3g})", fontsize=9, ha="left")
+
+ # Plot 3: Histogram of errors
+ ax = axes[2]
+ n_bins = max(20, len(y_true) // 10)
+ counts, bins, _ = ax.hist(diff, bins=n_bins, density=True, color="black", alpha=0.5)
+ ax.set_xlabel(f"{xlab} - {ylab}")
+ ax.set_ylabel("Density")
+ ax.set_title("Histogram")
+
+ mx_hist = float(np.max(counts)) if len(counts) > 0 else 0.1
+ ax.vlines(
+ mae,
+ 0,
+ mx_hist,
+ colors=COLOR_A,
+ linestyles="--",
+ linewidth=3,
+ label="mean error",
+ )
+ ax.vlines(0, 0, mx_hist, colors=COLOR_B, linestyles=":", linewidth=3, label="x=0")
+ ax.legend()
+
+ min_bin = float(min(bins)) if len(bins) > 0 else 0.0
+ ax.text(
+ min_bin,
+ mx_hist * 1.03,
+ f"(MAE = {mae:.3g} ± {sd_diff:.3g})",
+ fontsize=9,
+ ha="left",
+ )
+
+ plt.tight_layout()
+ plt.savefig(path, dpi=300)
+ plt.close()
+
+ return {
+ "intercept": intercept,
+ "slope": slope,
+ "mae": mae,
+ "sd_diff": sd_diff,
+ "correlation": correlation,
+ }
+
+
+def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
+ """
+ Fit robust linear model (RLM) and return intercept and slope.
+ """
+
+ x_rlm = sm.add_constant(x_values)
+ rlm_model = sm.RLM(y_values, x_rlm, M=sm.robust.norms.HuberT())
+ rlm_results = rlm_model.fit()
+ fit_params = rlm_results.params
+ intercept: float = fit_params[0]
+ slope: float = fit_params[1]
+ return intercept, slope
+
+
+def plot_ffx(
+ x_values: np.ndarray,
+ y_values: np.ndarray,
+ intercept: float,
+ slope: float,
+ out_dir_path: Path,
+):
+ """
+ Plot RLM fit results.
+ """
+ _, axes = plt.subplots(1, 2, figsize=(10, 5))
+ ax = axes[0]
+ ax.scatter(x_values, y_values, s=10, c="black", alpha=0.6)
+ ax.set_xlabel("FF (%)")
+ ax.set_ylabel("μ(ratio X)")
+ mx = max(x_values) if len(x_values) > 0 else 1
+ ax.set_xlim(0, mx)
+ x_range = np.array(
+ [
+ min(x_values) if len(x_values) > 0 else 0,
+ max(x_values) if len(x_values) > 0 else 1,
+ ]
+ )
+ y_range = intercept + slope * x_range
+ ax.plot(
+ x_range,
+ y_range,
+ color=COLOR_A,
+ linestyle="--",
+ linewidth=2,
+ label="RLM fit",
+ )
+ ax.legend()
+ ax = axes[1]
+ y_values_corrected = (
+ (y_values - intercept) / slope if slope != 0 else y_values
+ )
+ ax.scatter(x_values, y_values_corrected, s=10, c="black", alpha=0.6)
+ ax.set_xlabel("FF (%)")
+ ax.set_ylabel("FFX (%)")
+ ax.set_xlim(0, mx)
+ ax.plot(
+ [x_range[0], x_range[1]],
+ [x_range[0], x_range[1]],
+ color=COLOR_B,
+ linestyle=":",
+ linewidth=3,
+ )
+ plt.tight_layout()
+ plt.savefig(out_dir_path / "FFX.png", dpi=300)
+ plt.close()
+
diff --git a/src/preface/lib/schemas.py b/src/preface/lib/schemas.py
new file mode 100644
index 0000000..201618b
--- /dev/null
+++ b/src/preface/lib/schemas.py
@@ -0,0 +1,21 @@
+import pandera.pandas as pa
+
+
+class SampleSchema(pa.DataFrameSchema):
+ """
+ Sample schema for samplesheet entries.
+ """
+ ff = pa.Column(float, checks=[pa.Check.ge(0.0), pa.Check.le(1.0)], nullable=True)
+ filepath = pa.Column(str, checks=[pa.Check.str_matches(r'.+\.bed$')])
+ id = pa.Column(str)
+ sex = pa.Column(str, checks=pa.Check.isin(["M", "F"]))
+
+
+class SampleDataSchema(pa.DataFrameSchema):
+ """
+ Sample data model for samplesheet entries with optional fetal fraction.
+ """
+ chr = pa.Column(str, checks=pa.Check.str_matches(r'^(chr)?([1-9]|1[0-9]|2[0-2]|X|Y|MT)$'))
+ start = pa.Column(int, checks=pa.Check.ge(0), coerce=True)
+ end = pa.Column(int, checks=pa.Check.ge(0), coerce=True)
+ ratio = pa.Column(float, checks=[pa.Check.ge(0.0), pa.Check.le(1.0)], nullable=True)
diff --git a/src/preface/predict.py b/src/preface/predict.py
index 951ee81..07a5c70 100644
--- a/src/preface/predict.py
+++ b/src/preface/predict.py
@@ -2,8 +2,6 @@
Predict module for PREFACE.
"""
-# pylint: disable=too-many-locals,too-many-branches,too-many-statements
-
import os
import json
from typing import Optional, Union
diff --git a/src/preface/preface.py b/src/preface/preface.py
index 1b2a1f2..d852fb7 100644
--- a/src/preface/preface.py
+++ b/src/preface/preface.py
@@ -3,15 +3,20 @@
"""
import typer
+import importlib.metadata
+
from preface.predict import preface_predict
from preface.train import preface_train
from preface.utils.npz_to_parquet import npz_to_parquet
-from preface.utils.ffy import ffy
+from preface.utils.ffy import wisecondorx_ffy
from preface import __version__
# Version
VERSION: str = __version__
+AUTHORS: str = importlib.metadata.metadata("preface")["authors"]
+
+print(AUTHORS)
# Initialize Typer app
app = typer.Typer(help="PREFACE - PREdict FetAl ComponEnt")
@@ -21,7 +26,7 @@
# Utilities group
utils_app = typer.Typer(help="Utility scripts")
utils_app.command(name="npz-to-parquet")(npz_to_parquet)
-utils_app.command(name="ffy")(ffy)
+utils_app.command(name="ffy")(wisecondorx_ffy)
app.add_typer(utils_app, name="utils")
if __name__ == "__main__":
diff --git a/src/preface/train.py b/src/preface/train.py
index 834a9f0..1ae804a 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -4,515 +4,274 @@
import os
import time
-from typing import List, Optional, Any, Dict, Union
from pathlib import Path
-import numpy as np
import pandas as pd
-import joblib
-import matplotlib.pyplot as plt
-import statsmodels.api as sm
-from sklearn.decomposition import PCA
-from sklearn.linear_model import LinearRegression
-from joblib import Parallel, delayed
-from tensorflow import keras
-from tensorflow.keras import layers
import typer
-
+from pandera.errors import SchemaError
+import sklearn
+from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
+from sklearn.impute import IterativeImputer
+from sklearn.decomposition import PCA
+from sklearn.metrics import f1_score, mean_absolute_error, r2_score, roc_auc_score
+from sklearn.model_selection import KFold
+from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
+
+from preface.lib.functions import (
+ build_ensemble,
+ build_multi_output_nn,
+ plot_regression_performance,
+ preprocess_ratios,
+)
+from preface.lib.schemas import SampleDataSchema, SampleSchema
# Constants
-EXCLUDE_CHRS: List[str] = ['13', '18', '21', 'X', 'Y']
-COLOR_A: str = '#8DD1C6'
-COLOR_B: str = '#E3C88A'
-COLOR_C: str = '#C87878'
-
-
-def get_mean_diff(v1: np.ndarray, v2: np.ndarray, abs_val: bool = True) -> float:
- """Calculate mean difference."""
- if not abs_val:
- return float(np.mean(v1 - v2))
- return float(np.mean(np.abs(v1 - v2)))
-
-
-def get_std_diff(v1: np.ndarray, v2: np.ndarray) -> float:
- """Calculate standard deviation of difference."""
- return float(np.std(np.abs(v1 - v2), ddof=1)) # ddof=1 for sample sd
-
-
-def plot_performance(
- v1: np.ndarray,
- v2: np.ndarray,
- pca_explained_variance_ratio: np.ndarray,
- n_feat: int,
- xlab: str,
- ylab: str,
- path: str
-) -> List[float]:
- """Plot performance metrics."""
-
- # R plot layout: 1 row, 3 columns.
- _, axes = plt.subplots(1, 3, figsize=(15, 5))
-
- # Plot 1: PCA Importance
- ax = axes[0]
- y_vals = pca_explained_variance_ratio
- x_vals = np.arange(1, len(y_vals) + 1)
-
- # Filtering zeros for log
- mask = y_vals > 0
- x_vals = x_vals[mask]
- y_vals = y_vals[mask]
-
- ax.plot(np.log(x_vals), np.log(y_vals), color=COLOR_A, linewidth=2)
- ax.set_xlabel('Principal components (log scale)')
- ax.set_ylabel('Proportion of variance (log scale)')
- ax.set_title('PCA')
-
- # Vertical line at n_feat
- log_n_feat = np.log(n_feat)
- ylim = ax.get_ylim()
- ax.vlines(
- log_n_feat,
- ylim[0],
- ylim[1] * 0.99,
- colors=COLOR_C,
- linestyles='dotted',
- linewidth=3
- )
- ax.text(
- log_n_feat,
- ylim[1],
- 'Number of features',
- color=COLOR_C,
- ha='center',
- va='bottom',
- fontsize=8
- )
-
- # Plot 2: Scatter Plot
- ax = axes[1]
- mx = max(float(np.max(v1)), float(np.max(v2)))
- ax.scatter(v1, v2, s=10, c='black', alpha=0.6)
- ax.set_xlabel(xlab)
- ax.set_ylabel(ylab)
- ax.set_xlim(0, mx)
- ax.set_ylim(0, mx)
- ax.set_title('Scatter plot')
-
- # OLS fit
- intercept: float = 0.0
- slope: float = 0.0
- correlation: float = 0.0
-
- if len(np.unique(v1)) > 1:
- reg = LinearRegression().fit(v1.reshape(-1, 1), v2)
- fit_line = reg.predict(np.array([[0], [mx]]))
- ax.plot([0, mx], fit_line, color=COLOR_A, linestyle='--', linewidth=2, label='OLS fit')
- intercept = float(reg.intercept_)
- slope = float(reg.coef_[0])
- correlation = float(np.corrcoef(v1, v2)[0, 1])
- else:
- # Fallback if v1 is constant
- mean_v2 = float(np.mean(v2))
- ax.plot(
- [0, mx],
- [mean_v2, mean_v2],
- color=COLOR_A,
- linestyle='--',
- linewidth=2,
- label='Mean fit'
- )
- intercept = mean_v2
- slope = 0.0
- correlation = 0.0
-
- # Identity line
- ax.plot([0, mx], [0, mx], color=COLOR_B, linestyle=':', linewidth=3, label='f(x)=x')
-
- ax.legend()
- ax.text(0, mx * 1.03, f'(r = {correlation:.3g})', fontsize=9, ha='left')
-
- # Plot 3: Histogram of errors
- ax = axes[2]
- errors = v1 - v2
- n_bins = max(20, len(v1)//10)
- counts, bins, _ = ax.hist(errors, bins=n_bins, density=True, color='black', alpha=0.5)
- ax.set_xlabel(f'{xlab} - {ylab}')
- ax.set_ylabel('Density')
- ax.set_title('Histogram')
-
- mx_hist = float(np.max(counts)) if len(counts) > 0 else 0.1
- # Mean error line
- mean_err = get_mean_diff(v1, v2, abs_val=False)
- ax.vlines(
- mean_err, 0, mx_hist, colors=COLOR_A, linestyles='--', linewidth=3, label='mean error'
- )
- ax.vlines(0, 0, mx_hist, colors=COLOR_B, linestyles=':', linewidth=3, label='x=0')
- ax.legend()
-
- mae = get_mean_diff(v1, v2)
- sd_diff = get_std_diff(v1, v2)
- min_bin = float(min(bins)) if len(bins) > 0 else 0.0
- ax.text(
- min_bin,
- mx_hist * 1.03,
- f'(MAE = {mae:.3g} ± {sd_diff:.3g})',
- fontsize=9,
- ha='left'
- )
-
- plt.tight_layout()
- plt.savefig(path, dpi=300)
- plt.close()
-
- return [intercept, slope, mae, sd_diff, correlation]
-
-
-def train_neural_network(
- x_train: np.ndarray, y_train: np.ndarray, hidden_units: int
-) -> keras.Model:
- """Train a simple neural network."""
- model = keras.Sequential([
- layers.Input(shape=(x_train.shape[1],)),
- layers.Dense(hidden_units, activation='sigmoid'),
- layers.Dense(1, activation='linear')
- ])
-
- model.compile(optimizer='adam', loss='mse')
-
- early_stop = keras.callbacks.EarlyStopping(
- monitor='loss', patience=10, restore_best_weights=True
- )
-
- model.fit(
- x_train, y_train, epochs=200, batch_size=32, verbose=0, callbacks=[early_stop]
- )
- return model
+EXCLUDE_CHRS: list[str] = ['13', '18', '21', 'X', 'Y']
def preface_train(
- config_file: Path = typer.Option(..., "--config", help="Path to config file"),
+ samplesheet: Path = typer.Option(..., "--samplesheet", help="Path to samplesheet file"),
out_dir: Path = typer.Option(..., "--outdir", help="Output directory"),
n_feat: int = typer.Option(50, "--nfeat", help="Number of features (PCA components)"),
- hidden: int = typer.Option(2, "--hidden", help="Hidden units in NN"),
- cpus: int = typer.Option(1, "--cpus", help="Number of CPUs"),
- femprop: bool = typer.Option(False, "--femprop", help="Include females in training"),
- olm: bool = typer.Option(False, "--olm", help="Use Ordinary Linear Model instead of NN"),
- noskewcorrect: bool = typer.Option(False, "--noskewcorrect", help="Disable skew correction")
+ n_folds: int = typer.Option(5, "--nfolds", help="Number of folds for cross-validation"),
+ n_neurons: int = typer.Option(2, "--neurons", help="Number of initial neurons in neural network"),
+ exclude_chrs: list[str] = typer.Option(EXCLUDE_CHRS, "--exclude-chrs", help="Chromosomes to exclude from training"),
+ impute: bool = typer.Option(False, "--impute", help="Impute missing values instead of assuming zero")
) -> None:
"""
Train the PREFACE model.
"""
- start_time = time.time()
- train_sex: List[str] = ['M', 'F'] if femprop else ['M']
+ start_time: float = time.time()
- out_dir_path: str = os.path.join(out_dir, '')
-
- # Load config
- config = pd.read_csv(
- config_file, sep='\t', comment='#', dtype={'sex': str, 'ID': str}
+ # Load samplesheet
+ samplesheet_data: pd.DataFrame = pd.read_csv(
+ samplesheet, comment='#', dtype={'sex': str, 'ID': str}, index_col='ID'
)
+ # Validate samplesheet
+ samplesheet_schema = SampleSchema()
+ try:
+ samplesheet_schema.validate(samplesheet_data)
+ except SchemaError as e:
+ typer.echo(f"Error validating samplesheet: {e}")
+ raise typer.Exit(code=1)
+
# Check samples
- labeled_samples = config[config['sex'].isin(train_sex)]
- if len(labeled_samples) < n_feat:
+ if len(samplesheet_data) < n_feat:
typer.echo(f"Please provide at least {n_feat} labeled samples.")
raise typer.Exit(code=1)
- # Load first file for structure
- first_path: str = str(config['filepath'].iloc[0])
- training_frame_meta = load_bed_full(first_path)
- training_frame_meta = training_frame_meta[['chr', 'start', 'end']]
-
- # Load all ratios in parallel
+ # Load all sample data
typer.echo("Loading samples...")
- results: List[pd.DataFrame] = Parallel(n_jobs=cpus)(
- delayed(pd.read_csv)(str(f), sep='\t') for f in config['filepath']
- )
- lengths: List[int] = [len(x) for x in results if x is not None]
- if len(set(lengths)) > 1:
- typer.echo("Error: Input BED files have different numbers of bins (excluding Y).")
- raise typer.Exit(code=1)
-
- # Filter out Nones and stack
- valid_results: List[np.ndarray] = [res for res in results if res is not None]
- training_frame_sub = np.column_stack(valid_results)
-
- # Ensure meta alignment
- training_frame_meta = training_frame_meta[training_frame_meta['chr'] != 'Y']
- if len(training_frame_meta) != training_frame_sub.shape[0]:
- typer.echo("Mismatch in row counts between metadata and loaded data.")
- raise typer.Exit(code=1)
-
- is_x = training_frame_meta['chr'] == 'X'
- x_ratios_raw = training_frame_sub[is_x, :]
- x_ratios = 2 ** np.nanmean(x_ratios_raw, axis=0)
+ # instantiate lists for ratios
+ ratios_list: list[pd.DataFrame] = []
+
+ # instantiate schema
+ sample_data_schema = SampleDataSchema()
+
+ # instantiate number of bins checker
+ number_of_bins: int = -1
+
+ # parse data
+ for _, sample in samplesheet_data.iterrows():
+ if not Path(sample['filepath']).exists() or not Path(sample['filepath']).is_file():
+ typer.echo(f"Error: File '{sample['filepath']}' does not exist.")
+ raise typer.Exit(code=1)
+ # load ratios (bed format)
+ ratios = pd.read_csv(sample['filepath'], dtype={'chr': str, 'start': int, 'end': int, 'ratio': float}, sep='\t', header=0)
+ # validate ratios
+ try:
+ sample_data_schema.validate(ratios)
+ except SchemaError as e:
+ typer.echo(f"Error validating sample data for file {sample['filepath']}: {e}")
+ raise typer.Exit(code=1)
+
+ # check number of bins consistency
+ number_of_bins_current = len(ratios)
+ if number_of_bins == -1:
+ number_of_bins = number_of_bins_current
+ elif number_of_bins != number_of_bins_current:
+ typer.echo("Error: Input BED files have different numbers of bins.")
+ raise typer.Exit(code=1)
+
+ # preprocess ratios
+ masked_ratios = preprocess_ratios(ratios, exclude_chrs)
+
+ # add sample metadata columns to transposed ratios
+ masked_ratios['id'] = sample['ID']
+ masked_ratios['sex'] = sample['sex']
+ masked_ratios['ff'] = sample['FF']
+
+ # add to list
+ ratios_list.append(masked_ratios)
+
+ # Stack dataframes horizontally
+ typer.echo("Merging sample data...")
+ ratios_per_sample: pd.DataFrame = pd.concat(ratios_list, axis=0)
+
+ # set index to ID column
+ ratios_per_sample = ratios_per_sample.set_index('id')
typer.echo("Creating training frame...")
- mask_keep = ~training_frame_meta['chr'].isin(EXCLUDE_CHRS)
-
- training_frame_filtered = training_frame_sub[mask_keep, :]
- training_frame_meta_filtered = training_frame_meta[mask_keep]
-
- # Transpose: Samples as rows, Features as columns
- training_frame = training_frame_filtered.T
-
- feature_names = (
- training_frame_meta_filtered['chr'].astype(str) + ':' +
- training_frame_meta_filtered['start'].astype(str) + '-' +
- training_frame_meta_filtered['end'].astype(str)
- ).values
-
- training_df = pd.DataFrame(training_frame, columns=feature_names)
-
- # Filter NAs
- na_threshold = len(config) * 0.01
- cols_to_keep = training_df.isna().sum() < na_threshold
- training_df = training_df.loc[:, cols_to_keep]
-
- possible_features = training_df.columns.values
- mean_features = training_df.mean()
-
- training_df = training_df.fillna(mean_features)
-
- typer.echo(f"Remaining training features after 'NA' filtering: {len(possible_features)}")
-
- os.makedirs(os.path.join(out_dir_path, 'training_repeats'), exist_ok=True)
-
- repeats: int = 10
- test_percentage: float = 1.0 / repeats
-
- train_mask = config['sex'].isin(train_sex)
- train_indices_all: List[int] = config.index[train_mask].tolist()
-
- n_train_samples: int = len(train_indices_all)
- test_number: int = int(n_train_samples * test_percentage)
-
- max_feat: int = n_train_samples - test_number - 1
- if n_feat > max_feat:
- typer.echo(f"Too few samples were provided for --nfeat {n_feat}, using --nfeat {max_feat}")
- n_feat = max_feat
-
- train_subset_df = training_df.iloc[train_indices_all].reset_index(drop=True)
- y_all: np.ndarray = config.loc[train_indices_all, 'FF'].astype(float).values
-
- results_repeats: List[Dict[str, Any]] = []
-
- for i in range(1, repeats + 1):
- typer.echo(f"Model training | Repeat {i}/{repeats} ...")
-
- start_idx: int = int((i - 1) * test_number)
- end_idx: int = int(i * test_number)
-
- test_idxs_local: List[int] = list(range(start_idx, end_idx))
- train_idxs_local: List[int] = list(set(range(len(train_subset_df))) - set(test_idxs_local))
-
- x_tr_local = train_subset_df.iloc[train_idxs_local]
- x_te_local = train_subset_df.iloc[test_idxs_local]
- y_tr_local = y_all[train_idxs_local]
- y_te_local = y_all[test_idxs_local]
-
- typer.echo("\tExecuting principal component analysis ...")
- n_components_pca: int = min(n_feat * 10, len(x_tr_local) - 1)
- pca = PCA(n_components=n_components_pca)
- pca.fit(x_tr_local)
-
- x_train_pca = pca.transform(x_tr_local)
- x_test_pca = pca.transform(x_te_local)
-
- x_train_model = x_train_pca[:, :n_feat]
- x_test_model = x_test_pca[:, :n_feat]
+ # Handle NaN values
+ # Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
+ # Since the input log2 ratios indicate relative coverage to a reference,
+ # we can either impute missing values with the mean ratio of that feature
+ # or assume zero (no change).
+ # Option 1: Impute NaN through MICE (Multiple Imputation by Chained Equations)
+ if impute:
+ # Check sklearn version for compatibility
+ sk_version = sklearn.__version__
+ if sk_version != "1.8.0":
+ typer.echo(f"""Warning: PREFACE uses imputation and was developed using scikit-learn version 1.8.0.
+ Since imputation is still experimental, it may be subject to change in other versions.
+ You are using version {sk_version}. Proceed with caution.""")
+
+ typer.echo("Imputing missing values using MICE...")
+
+ imputer = IterativeImputer(random_state=42, max_iter=10, initial_strategy='mean')
+ training_df_array = imputer.fit_transform(ratios_per_sample)
+ ratios_per_sample = pd.DataFrame(
+ training_df_array,
+ index=ratios_per_sample.index,
+ columns=ratios_per_sample.columns
+ )
+ # Option 2: Assume missing values are zero (no change)
+ else:
+ typer.echo("Assuming missing values are zero...")
+ ratios_per_sample = ratios_per_sample.fillna(0.0)
+
+ # Split into features and labels
+ x_all: pd.DataFrame = ratios_per_sample.drop(columns=['sex', 'ff'])
+ # labels for regression (fetal fraction)
+ y_ff_all = ratios_per_sample['ff']
+ # labels for classification (sex)
+ y_sex_all = (
+ ratios_per_sample['sex']
+ .map({"M": 1, "F": 0})
+ .astype(float)
+ .values
+ )
- prediction: Optional[np.ndarray] = None
- if olm:
- typer.echo("\tTraining ordinary linear model ...")
- model = LinearRegression()
- model.fit(x_train_model, y_tr_local)
- prediction = model.predict(x_test_model)
- else:
- typer.echo("\tTraining neural network ...")
- model = train_neural_network(x_train_model, y_tr_local, hidden)
- prediction = model.predict(x_test_model).flatten()
+ # Reduce dimensionality with PCA
+ global_pca = PCA(n_components=n_feat)
+ x_all_pca = global_pca.fit_transform(x_all)
+
+ # Set up training
+ # Create directory to store fold metrics
+ os.makedirs(out_dir / 'training_folds', exist_ok=True)
+ fold_metrics = []
+ fold_models: list[keras.Model] = []
+
+ # Set up k-fold cross-validation
+ kf: KFold = KFold(n_splits=n_folds, shuffle=True, random_state=42)
+ for fold, (train_idx, test_idx) in enumerate(kf.split(x_all_pca), 1):
+ typer.echo(f"Processing Fold {fold}/{n_folds}...")
+
+ # split into train and test sets
+ x_train, x_test = x_all_pca[train_idx], x_all_pca[test_idx]
+ y_ff_train, y_ff_test = y_ff_all[train_idx], y_ff_all[test_idx]
+ y_sex_train, y_sex_test = y_sex_all[train_idx], y_sex_all[test_idx]
+
+ # Create new model instance
+ model = build_multi_output_nn(input_dim=n_feat, n_neurons=n_neurons)
+
+ # Train
+ typer.echo(f"Training fold {fold}...")
+ # Early stopping callback
+ early_stop = keras.callbacks.EarlyStopping(
+ monitor='val_loss',
+ patience=5,
+ restore_best_weights=True
+ )
+ # Fit model
+ model.fit(
+ x_train,
+ {"reg_output": y_ff_train, "class_output": y_sex_train},
+ validation_data=(
+ x_test,
+ {"reg_output": y_ff_test, "class_output": y_sex_test},
+ ),
+ epochs=100,
+ batch_size=32,
+ verbose=1,
+ callbacks=[early_stop],
+ )
- info = plot_performance(
- prediction,
- y_te_local,
- pca.explained_variance_ratio_,
+ # Save fold model
+ model.save(out_dir / 'training_folds' / f'fold_{fold}.keras')
+ fold_models.append(model)
+
+ # Evaluate
+ predictions = model.predict(x_test)
+ y_ff_pred = predictions[0].flatten()
+ class_pred_probs = predictions[1].flatten()
+ class_pred = (class_pred_probs >= 0.5).astype(int)
+
+ # Plot regression performance
+ reg_perf = plot_regression_performance(
+ y_ff_pred,
+ y_ff_test.to_numpy(),
+ global_pca.explained_variance_ratio_,
n_feat,
- 'PREFACE (%)',
- 'FF (%)',
- os.path.join(out_dir_path, 'training_repeats', f'repeat_{i}.png')
+ "PREFACE (%)",
+ "FF (%)",
+ out_dir / "training_folds" / f"fold_{fold}_regression.png",
)
- results_repeats.append({
- 'intercept': info[0],
- 'slope': info[1],
- 'prediction': prediction
- })
-
- predictions: np.ndarray = np.concatenate([r['prediction'] for r in results_repeats])
-
- the_intercept: float = 0.0
- the_slope: float = 1.0
-
- n_used: int = int(test_number * repeats)
- y_used: np.ndarray = y_all[:n_used]
-
- if not noskewcorrect:
- np.random.seed(1)
- n_pred: int = len(predictions)
- p: np.ndarray = np.random.choice(n_pred, max(1, n_pred // 4), replace=False)
-
- pred_p = predictions[p]
- y_p = y_used[p]
-
- reg_skew = LinearRegression().fit(pred_p.reshape(-1, 1), y_p)
- the_intercept = float(reg_skew.intercept_)
- the_slope = float(reg_skew.coef_[0])
-
- typer.echo("Correction for skew:")
- typer.echo(f"\tIntercept: {the_intercept}")
- typer.echo(f"\tSlope: {the_slope}")
-
- typer.echo("Training FFX Model...")
-
- mask_m = config['sex'] == 'M'
- v1_m: np.ndarray = config.loc[mask_m, 'FF'].astype(float).values
- v2_m: np.ndarray = x_ratios[mask_m]
-
- x_rlm = sm.add_constant(v1_m)
- rlm_model = sm.RLM(v2_m, x_rlm, M=sm.robust.norms.HuberT())
- rlm_results = rlm_model.fit()
-
- fit_params = rlm_results.params
- intercept_x: float = fit_params[0]
- slope_x: float = fit_params[1]
-
- _, axes = plt.subplots(1, 2, figsize=(10, 5))
- ax = axes[0]
- ax.scatter(v1_m, v2_m, s=10, c='black', alpha=0.6)
- ax.set_xlabel('FF (%)')
- ax.set_ylabel('μ(ratio X)')
- mx = max(v1_m) if len(v1_m) > 0 else 1
- ax.set_xlim(0, mx)
-
- x_range = np.array(
- [min(v1_m) if len(v1_m) > 0 else 0, max(v1_m) if len(v1_m) > 0 else 1]
+ # Calculate metrics
+ metrics: dict = {
+ # fold number
+ 'fold': fold,
+ # regression metrics
+ 'ff_mae': mean_absolute_error(y_ff_test, y_ff_pred),
+ 'ff_r2': r2_score(y_ff_test, y_ff_pred),
+ 'ff_intercept': reg_perf['intercept'],
+ 'ff_slope': reg_perf['slope'],
+ # classification metrics
+ 'sex_f1': f1_score(y_sex_test, class_pred), # type: ignore
+ 'sex_auc': roc_auc_score(y_sex_test, class_pred_probs) # type: ignore
+ }
+ fold_metrics.append(metrics)
+
+ # Save fold metrics to a DataFrame
+ fold_metrics_df = pd.DataFrame(fold_metrics)
+ fold_metrics_df.to_csv(
+ out_dir / 'training_fold_metrics.csv', index=False
)
- y_range = intercept_x + slope_x * x_range
- ax.plot(x_range, y_range, color=COLOR_A, linestyle='--', linewidth=2, label='RLS fit')
- ax.legend()
-
- ax = axes[1]
- v2_corrected = (v2_m - intercept_x) / slope_x if slope_x != 0 else v2_m
- ax.scatter(v1_m, v2_corrected, s=10, c='black', alpha=0.6)
- ax.set_xlabel('FF (%)')
- ax.set_ylabel('FFX (%)')
- ax.set_xlim(0, mx)
- ax.plot(
- [x_range[0], x_range[1]], [x_range[0], x_range[1]],
- color=COLOR_B, linestyle=':', linewidth=3
- )
-
- plt.tight_layout()
- plt.savefig(os.path.join(out_dir_path, 'FFX.png'), dpi=300)
- plt.close()
-
- predictions_corrected = the_intercept + the_slope * predictions
-
- typer.echo("Executing final principal component analysis ...")
-
- pca_final = PCA(n_components=min(n_feat * 10, len(train_subset_df) - 1))
- pca_final.fit(train_subset_df)
- x_train_final = pca_final.transform(train_subset_df)[:, :n_feat]
- y_train_final = y_all
-
- model_final: Union[LinearRegression, keras.Model]
- if olm:
- typer.echo("Training final ordinary linear model ...")
- model_final = LinearRegression()
- model_final.fit(x_train_final, y_train_final)
- else:
- typer.echo("Training final neural network ...")
- model_final = train_neural_network(x_train_final, y_train_final, hidden)
-
- info_overall = plot_performance(
- predictions_corrected,
- y_used,
- pca_final.explained_variance_ratio_,
+ # Build ensemble model from fold models
+ typer.echo("Building ensemble model from fold models...")
+ ensemble_model = build_ensemble(len(x_all.columns), global_pca, fold_models)
+ ensemble_model.save(out_dir / 'PREFACE')
+
+ # Final evaluation on all training data
+ typer.echo("Evaluating final model on all training data...")
+ predictions = ensemble_model.predict(x_all)
+ info_overall = plot_regression_performance(
+ predictions[0].flatten(),
+ y_ff_all.to_numpy(),
+ global_pca.explained_variance_ratio_,
n_feat,
'PREFACE (%)',
'FF (%)',
- os.path.join(out_dir_path, 'overall_performance.png')
+ out_dir / 'overall_performance.png'
)
- deviations = np.abs(predictions_corrected - y_used)
- mae = info_overall[2]
- sd = info_overall[3]
- outlier_threshold = mae + 3 * sd
- outlier_indices = np.where(deviations > outlier_threshold)[0]
-
with open(
- os.path.join(out_dir_path, 'training_statistics.txt'), 'w', encoding='utf-8'
+ out_dir / 'training_statistics.txt', 'w', encoding='utf-8'
) as f:
- f.write('PREFACE - PREdict FetAl ComponEnt\n\n')
-
- if len(outlier_indices) > 0:
- f.write('Below, some of the top candidates for outlier removal are listed.\n')
- f.write('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- _\n')
- f.write('ID\tFF (%) - PREFACE (%)\n')
-
- sorted_outlier_idxs = outlier_indices[np.argsort(-deviations[outlier_indices])]
- subset_ids = config.loc[train_indices_all, 'ID'].values[:n_used]
- subset_diffs = predictions_corrected - y_used
-
- for idx in sorted_outlier_idxs:
- f.write(f"{subset_ids[idx]}\t{subset_diffs[idx]:.4f}\n")
- f.write('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- _\n\n')
-
- elapsed_time = time.time() - start_time
- f.write(f"Training time: {elapsed_time:.0f} seconds\n")
- f.write(f"Overall correlation (r): {info_overall[4]:.4f}\n")
f.write(
- f"Overall mean absolute error (MAE): "
- f"{info_overall[2]:.4f} ± {info_overall[3]:.4f}\n"
+ f"""PREFACE - PREdict FetAl ComponEnt
+ Training time: {time.time() - start_time:.0f} seconds
+ Overall correlation (r): {info_overall["correlation"]:.4f}
+ Overall mean absolute error (MAE): {info_overall["mae"]:.4f} ± {info_overall["sd_diff"]:.4f}
+ """
)
- mask_10 = y_used < 10.0
- if np.any(mask_10):
- devs_10 = deviations[mask_10]
- f.write(
- f"FF < 10% mean absolute error (MAE): "
- f"{np.mean(devs_10):.4f} ± {np.std(devs_10, ddof=1):.4f}\n"
- )
-
- f.write("Correction for skew: \n")
- f.write(f"\tIntercept: {the_intercept}\n")
- f.write(f"\tSlope: {the_slope}\n\n")
-
- model_data = {
- 'n_feat': n_feat,
- 'mean_features': mean_features,
- 'possible_features': possible_features,
- 'pca': pca_final,
- 'is_olm': olm,
- 'the_intercept': the_intercept,
- 'the_slope': the_slope,
- 'the_intercept_X': intercept_x,
- 'the_slope_X': slope_x,
- }
-
- joblib.dump(model_data, os.path.join(out_dir_path, 'model_meta.pkl'))
-
- if olm:
- joblib.dump(model_final, os.path.join(out_dir_path, 'model_weights.pkl'))
- else:
- model_final.save(os.path.join(out_dir_path, 'model_weights.keras'))
-
typer.echo(
- f"Finished! Consult '{out_dir_path}training_statistics.txt' "
+ f"Finished! Consult '{out_dir / 'training_statistics.txt'}' "
"to analyse your model's performance."
)
From 9d0a9b4231a431c78847356f36f1f83d294436df Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 26 Dec 2025 22:40:47 +0100
Subject: [PATCH 08/50] linting
---
src/preface/lib/functions.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index 1f50a1f..a997c7a 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -3,11 +3,11 @@
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
-from sklearn.decomposition import PCA
import statsmodels.api as sm
+import tensorflow as tf
+from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
-import tensorflow as tf
from tensorflow.keras import ( # pylint: disable=no-name-in-module,import-error # type: ignore
Model,
layers,
@@ -92,7 +92,7 @@ def build_ensemble(n_feat: int, pca: PCA, models: list[Model]) -> Model:
class_outputs = []
for i, fold_model in enumerate(models):
- fold_model._name = f"fold_model_{i}" # Ensure unique names
+ fold_model.name = f"fold_model_{i}" # Ensure unique names
# Pass the PCA features through the fold model
reg_out, class_out = fold_model(pca_feat)
From 3efbfba698700bc5d73abc12f51272479f804ee2 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sat, 27 Dec 2025 15:29:57 +0100
Subject: [PATCH 09/50] refactoring + hyperparameter tuning
---
README.md | 62 ++--
examples/{infile.bed => ratios.bed} | 0
examples/{config.txt => samplesheet.tsv} | 0
pixi.lock | 361 ++++++++++++++++++++++-
pyproject.toml | 2 +-
src/preface/lib/functions.py | 63 ++--
src/preface/lib/neural.py | 138 +++++++++
src/preface/lib/schemas.py | 8 +-
src/preface/lib/xgboost.py | 88 ++++++
src/preface/predict.py | 161 +++++-----
src/preface/preface.py | 10 +-
src/preface/train.py | 199 ++++++++-----
src/preface/utils/ffy.py | 10 +-
src/preface/utils/npz_to_parquet.py | 4 +-
14 files changed, 850 insertions(+), 256 deletions(-)
rename examples/{infile.bed => ratios.bed} (100%)
rename examples/{config.txt => samplesheet.tsv} (100%)
create mode 100644 src/preface/lib/neural.py
create mode 100644 src/preface/lib/xgboost.py
diff --git a/README.md b/README.md
index 5b65978..1bbb4a5 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ A share of all cell-free DNA fragments isolated from maternal plasma during preg
Each sample (whether it is used for training or for predicting) should be passed to PREFACE in the format shown below. During benchmarking, using a bin size of 100 kb (others might work equally well), copy number normalization was performed by [WisecondorX](https://github.com/CenterForMedicalGeneticsGhent/WisecondorX/), yet PREFACE is not limited to any copy number alteration software, however, the default output of WisecondorX is directly interpretable by PREFACE.
-- Example: ```./examples/infile.bed```
+- Example: ```./examples/ratios.bed```
- Tab-separated file with at least four columns.
- The name of these columns (passed as a header) must be 'chr', 'start', 'end' and 'ratio'.
- The possible values of 'chr' are 1 until 22, and X and Y (uppercase).
@@ -18,17 +18,17 @@ Each sample (whether it is used for training or for predicting) should be passed
- The ratio can be unknown at certain loci (e.g. often seen at centromeres). Here, values should be expressed as 'NaN' or 'NA'.
- The order of rows does not matter. Yet, it is paramount that, for a certain line, file x deals with the same locus as file y. This implies, of course, that all copy number alteration files have the same number of lines.
-### PREFACE's config.txt
+### PREFACE's samplesheet.tsv
-For training, PREFACE requires a config file.
+For training, PREFACE requires a samplesheet file.
-- Example: ```./examples/config.txt```
-- Tab-separated file with at least four columns.
-- The name of these columns (passed as a header) must be 'ID', 'filepath', 'gender' and 'FF'.
+- Example: ```./examples/samplesheet.tsv```
+- TSV file with at least four columns.
+- The name of these columns (passed as a header) must be 'ID', 'filepath', 'sex' and 'FF'.
- 'ID' is used to specify a mandatory unique identifier to each of the samples.
- - The 'filepath' column holds the full absolute path of the training copy number alteration files.
- - The possible values for 'gender' are either 'M' (male) or 'F' (female), representing fetal gender. Twins/triplets/... can be included if they are all male or all female.
- - The 'FF' column contains the response variable (the 'true' fetal fraction). One can use any method he/she believes performs best at quantifying the actual fetal fraction. PREFACE was benchmarked using the number of mapped Y-reads, referred to as FFY. As FFY is not informative for female fetuses, this measure is ignored for cases labeled with 'F', unless the `--femprop` flag is given (see below).
+ - The 'filepath' column holds the full absolute path of the training copy number alteration files (.bed).
+ - The possible values for 'sex' are either 'M' (male) or 'F' (female), representing fetal gender.
+ - The 'FF' column contains the response variable (the 'true' fetal fraction). One can use any method he/she believes performs best at quantifying the actual fetal fraction. PREFACE was benchmarked using the number of mapped Y-reads, referred to as FFY.
## Installation & Setup
@@ -43,27 +43,28 @@ This will install the `PREFACE` command-line tool.
## Model training
```bash
-PREFACE train --config path/to/config.txt --outdir path/to/dir/ [optional arguments]
+PREFACE train --samplesheet path/to/samplesheet.tsv [optional arguments]
```
-
Optional argument
| Function
-:--- | :---
-`--nfeat x` | Number of principal components to use during modeling. (default: x=50)
-`--hidden x` | Number of hidden layers used in neural network. Use with caution. (default: x=2)
-`--cpus x` | Use for multiprocessing, number of requested threads. (default: x=1)
-`--femprop` | When using FFY as FF (recommended), FF labels for female fetuses are irrelevant, and should be ignored in the supervised learning phase (default). If this behavior is not desired, use this flag, which demands that the given FFs for female fetuses are proportional to their actual FF.
-`--olm` | It might be possible the neural network does not converge; or for your kind of data/sample size, an ordinary linear model might be a better option. In these cases, use this flag.
-`--noskewcorrect` | This flag ascertains the best fit for most (instead of all) of the data is generated. Mostly not recommended.
+| Optional argument | Function |
+| :--- | :--- |
+| `--impute` | Impute missing values instead of assuming zero. |
+| `--exclude-chrs` | Chromosomes to exclude from training (default: 13, 18, 21, X, Y). |
+| `--nfolds x` | Number of folds for cross-validation (default: 5). |
+| `--nfeat x` | Number of features (PCA components) (default: 50). |
+| `--tune` | Enable automatic hyperparameter tuning. |
+| `--model [neural\|xgboost]` | Type of model to train (default: neural). |
## Predicting
```bash
-PREFACE predict --infile path/to/infile.bed --model path/to/model_directory [optional arguments]
+PREFACE predict --infile path/to/infile.bed --model path/to/model_directory
```
-
Optional argument
| Function
-:--- | :---
-`--json x` | Predictions are written to stdout. Use this flag for json format. Optionally provide 'x' to generate .json file x.
+| Argument | Function |
+| :--- | :--- |
+| `--infile` | Path to input BED file. |
+| `--model` | Path to the trained model directory. |
## Model optimization
@@ -73,27 +74,32 @@ PREFACE predict --infile path/to/infile.bed --model path/to/model_directory [opt
- A 'non-random' phase (representing PCs that explain variance caused by natural Gaussian noise).
- An optimal `--nfeat` captures the 'random' phase (as shown in the example at `./examples/overall_performance.png`). Capturing too much of the 'non-random' phase could lead to convergence problems during modeling.
- If you are not satisfied with the performance of your model or with the position of `--nfeat`, re-run with a different number of features.
-- Note that the final model will probably be a bit more accurate than what is claimed by the performance statistics. This is because PREFACE uses a cross-validation strategy where 10% of the (male) samples are excluded from training, after which these 10% serve as validation cases. This process is repeated 10 times. Therefore, the final performance measurements are based on models trained with only 90% of the (male) fetuses, yet the resulting model is trained with all provided cases.
+- Note that the final model will probably be a bit more accurate than what is claimed by the performance statistics. This is because PREFACE uses a cross-validation strategy where a subset of samples are excluded from training, after which these serve as validation cases. This process is repeated `n` times (default 5). Therefore, the final performance measurements are based on models trained with only partial data, yet the resulting model is trained with all provided cases.
# Utilities
## NPZ to Parquet Converter
-This script converts NumPy `.npz` files into one or more Parquet files, facilitating easier exploration and analysis of the stored numerical data using tools like Pandas. Each array within an `.npz` file will be converted to a separate Parquet file.
+This script converts NumPy `.npz` files into one or more Parquet files, facilitating easier exploration and analysis of the stored numerical data using tools like Pandas.
### Usage
```bash
-npz-to-parquet [ ...] [-o ]
+PREFACE utils npz-to-parquet [ ...] [-o ]
```
- ` [ ...]`: One or more paths to the input `.npz` files.
- `-o, --output-dir`: (Optional) Directory to save the output Parquet files. Defaults to the current directory (`.`).
-### Example
+## FFY Calculator
+
+Calculates Fetal Fraction from Y-chromosome reads (from WisecondorX NPZ output).
-To convert `data.npz` and `features.npz` and save the output Parquet files in a directory named `parquet_output`:
+### Usage
```bash
-npz-to-parquet data.npz features.npz -o parquet_output
+PREFACE utils ffy [--sex-cutoff ]
```
+
+- ``: Path to WisecondorX output NPZ file.
+- `--sex-cutoff`: (Optional) Cutoff for sex determination (default: 0.2).
\ No newline at end of file
diff --git a/examples/infile.bed b/examples/ratios.bed
similarity index 100%
rename from examples/infile.bed
rename to examples/ratios.bed
diff --git a/examples/config.txt b/examples/samplesheet.tsv
similarity index 100%
rename from examples/config.txt
rename to examples/samplesheet.tsv
diff --git a/pixi.lock b/pixi.lock
index 63382ce..5710509 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -43,17 +43,20 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
@@ -61,6 +64,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
@@ -70,8 +74,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
@@ -84,6 +90,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -91,12 +98,14 @@ environments:
- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
@@ -107,6 +116,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/5e/ab/c60fcc137fa685533bb31e721de3ecc88959d393830d59d0204c5cbd2c85/xgboost-3.1.2-py3-none-manylinux_2_28_x86_64.whl
- pypi: ./
linux-aarch64:
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2
@@ -142,17 +152,20 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
@@ -160,6 +173,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
@@ -171,6 +185,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
@@ -183,6 +198,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
@@ -190,12 +206,14 @@ environments:
- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
@@ -206,6 +224,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/70/2f/5418f4b1deaf0886caf81c5e056299228ac2fc09b965a2dfe5e4496331c8/xgboost-3.1.2-py3-none-manylinux_2_28_aarch64.whl
- pypi: ./
osx-arm64:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/astroid-4.0.2-py313h8f79df9_0.conda
@@ -235,11 +254,13 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
@@ -253,6 +274,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
@@ -264,6 +286,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
@@ -276,6 +299,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
@@ -283,12 +307,14 @@ environments:
- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
@@ -299,6 +325,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/f4/c6/ed928cb106f56ab73b3f4edb5287c1352251eb9225b5932d3dd5e2803f60/xgboost-3.1.2-py3-none-macosx_12_0_arm64.whl
- pypi: ./
packages:
- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
@@ -340,6 +367,17 @@ packages:
version: 2.3.1
sha256: eeecf07f0c2a93ace0772c92e596ace6d3d3996c042b2128459aaae2a76de11d
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
+ name: alembic
+ version: 1.17.2
+ sha256: f483dd1fe93f6c5d49217055e4d15b905b425b6af906746abb35b69c1996c4e6
+ requires_dist:
+ - sqlalchemy>=1.4.0
+ - mako
+ - typing-extensions>=4.12
+ - tomli ; python_full_version < '3.11'
+ - tzdata ; extra == 'tz'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
name: annotated-types
version: 0.7.0
@@ -470,6 +508,18 @@ packages:
- pkg:pypi/colorama?source=hash-mapping
size: 27011
timestamp: 1733218222191
+- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
+ name: colorlog
+ version: 6.10.1
+ sha256: 2d7e8348291948af66122cff006c9f8da6255d224e7cf8e37d8de2df3bad8c9c
+ requires_dist:
+ - colorama ; sys_platform == 'win32'
+ - black ; extra == 'development'
+ - flake8 ; extra == 'development'
+ - mypy ; extra == 'development'
+ - pytest ; extra == 'development'
+ - types-colorama ; extra == 'development'
+ requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
name: contourpy
version: 1.3.3
@@ -687,6 +737,28 @@ packages:
sha256: b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed
requires_dist:
- six
+- pypi: https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
+ name: greenlet
+ version: 3.3.0
+ sha256: 9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808
+ requires_dist:
+ - sphinx ; extra == 'docs'
+ - furo ; extra == 'docs'
+ - objgraph ; extra == 'test'
+ - psutil ; extra == 'test'
+ - setuptools ; extra == 'test'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
+ name: greenlet
+ version: 3.3.0
+ sha256: 087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527
+ requires_dist:
+ - sphinx ; extra == 'docs'
+ - furo ; extra == 'docs'
+ - objgraph ; extra == 'test'
+ - psutil ; extra == 'test'
+ - setuptools ; extra == 'test'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
name: grpcio
version: 1.76.0
@@ -1105,6 +1177,16 @@ packages:
purls: []
size: 46438
timestamp: 1727963202283
+- pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
+ name: mako
+ version: 1.3.10
+ sha256: baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59
+ requires_dist:
+ - markupsafe>=0.9.2
+ - pytest ; extra == 'testing'
+ - babel ; extra == 'babel'
+ - lingua ; extra == 'lingua'
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
name: markdown
version: '3.10'
@@ -1341,6 +1423,11 @@ packages:
version: 2.4.0
sha256: 39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d
requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
+ name: nvidia-nccl-cu12
+ version: 2.28.9
+ sha256: 485776daa8447da5da39681af455aa3b2c2586ddcf4af8772495e7c532c7e5ab
+ requires_python: '>=3'
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d
md5: 9ee58d5c534af06558933af3c845a780
@@ -1500,6 +1587,75 @@ packages:
- numpy ; extra == 'docs'
- torch ; extra == 'docs'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
+ name: optuna
+ version: 4.6.0
+ sha256: 4c3a9facdef2b2dd7e3e2a8ae3697effa70fae4056fcf3425cfc6f5a40feb069
+ requires_dist:
+ - alembic>=1.5.0
+ - colorlog
+ - numpy
+ - packaging>=20.0
+ - sqlalchemy>=1.4.2
+ - tqdm
+ - pyyaml
+ - asv>=0.5.0 ; extra == 'benchmark'
+ - cma ; extra == 'benchmark'
+ - virtualenv ; extra == 'benchmark'
+ - black<25.9.0 ; extra == 'checking'
+ - blackdoc<0.4.2 ; extra == 'checking'
+ - flake8 ; extra == 'checking'
+ - isort ; extra == 'checking'
+ - mypy ; extra == 'checking'
+ - mypy-boto3-s3 ; extra == 'checking'
+ - scipy-stubs ; python_full_version >= '3.10' and extra == 'checking'
+ - types-pyyaml ; extra == 'checking'
+ - types-redis ; extra == 'checking'
+ - types-setuptools ; extra == 'checking'
+ - types-tqdm ; extra == 'checking'
+ - typing-extensions>=3.10.0.0 ; extra == 'checking'
+ - ase ; extra == 'document'
+ - cmaes>=0.12.0 ; extra == 'document'
+ - fvcore ; extra == 'document'
+ - kaleido<0.4 ; extra == 'document'
+ - lightgbm ; extra == 'document'
+ - matplotlib!=3.6.0 ; extra == 'document'
+ - pandas ; extra == 'document'
+ - pillow ; extra == 'document'
+ - plotly>=4.9.0 ; extra == 'document'
+ - scikit-learn ; extra == 'document'
+ - sphinx ; extra == 'document'
+ - sphinx-copybutton ; extra == 'document'
+ - sphinx-gallery ; extra == 'document'
+ - sphinx-notfound-page ; extra == 'document'
+ - sphinx-rtd-theme>=1.2.0 ; extra == 'document'
+ - torch ; extra == 'document'
+ - torchvision ; extra == 'document'
+ - boto3 ; extra == 'optional'
+ - cmaes>=0.12.0 ; extra == 'optional'
+ - google-cloud-storage ; extra == 'optional'
+ - matplotlib!=3.6.0 ; extra == 'optional'
+ - pandas ; extra == 'optional'
+ - plotly>=4.9.0 ; extra == 'optional'
+ - redis ; extra == 'optional'
+ - scikit-learn>=0.24.2 ; extra == 'optional'
+ - scipy ; extra == 'optional'
+ - torch ; extra == 'optional'
+ - greenlet ; extra == 'optional'
+ - grpcio ; extra == 'optional'
+ - protobuf>=5.28.1 ; extra == 'optional'
+ - coverage ; extra == 'test'
+ - fakeredis[lua] ; extra == 'test'
+ - kaleido<0.4 ; extra == 'test'
+ - moto ; extra == 'test'
+ - pytest ; extra == 'test'
+ - pytest-xdist ; extra == 'test'
+ - scipy>=1.9.2 ; extra == 'test'
+ - torch ; extra == 'test'
+ - greenlet ; extra == 'test'
+ - grpcio ; extra == 'test'
+ - protobuf>=5.28.1 ; extra == 'test'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
name: packaging
version: '25.0'
@@ -1953,7 +2109,7 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: 8a47fcd7ffd33684027ee0a0a4c2eba532cf0181786f9e88a029e2dc1bf83b06
+ sha256: 781b8e425980ab36d861eb64e6211b9ccf74fc6759001690d1556f7475f63bd5
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -1964,6 +2120,8 @@ packages:
- statsmodels>=0.14.6,<0.15
- typer>=0.20.0,<0.21
- pandera>=0.27.1,<0.28
+ - xgboost>=3.1.2,<4
+ - optuna>=4.6.0,<5
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
@@ -2147,6 +2305,21 @@ packages:
name: pytz
version: '2025.2'
sha256: 5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
+- pypi: https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: pyyaml
+ version: 6.0.3
+ sha256: ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: pyyaml
+ version: 6.0.3
+ sha256: 0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
+ name: pyyaml
+ version: 6.0.3
+ sha256: 2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1
+ requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002
md5: d7d95fc8287ea7bf33e0e7116d2b95ec
@@ -2577,6 +2750,120 @@ packages:
version: 1.17.0
sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: sqlalchemy
+ version: 2.0.45
+ sha256: 672c45cae53ba88e0dad74b9027dddd09ef6f441e927786b05bec75d949fbb2e
+ requires_dist:
+ - importlib-metadata ; python_full_version < '3.8'
+ - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'
+ - typing-extensions>=4.6.0
+ - greenlet>=1 ; extra == 'asyncio'
+ - mypy>=0.910 ; extra == 'mypy'
+ - pyodbc ; extra == 'mssql'
+ - pymssql ; extra == 'mssql-pymssql'
+ - pyodbc ; extra == 'mssql-pyodbc'
+ - mysqlclient>=1.4.0 ; extra == 'mysql'
+ - mysql-connector-python ; extra == 'mysql-connector'
+ - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector'
+ - cx-oracle>=8 ; extra == 'oracle'
+ - oracledb>=1.0.1 ; extra == 'oracle-oracledb'
+ - psycopg2>=2.7 ; extra == 'postgresql'
+ - pg8000>=1.29.1 ; extra == 'postgresql-pg8000'
+ - greenlet>=1 ; extra == 'postgresql-asyncpg'
+ - asyncpg ; extra == 'postgresql-asyncpg'
+ - psycopg2-binary ; extra == 'postgresql-psycopg2binary'
+ - psycopg2cffi ; extra == 'postgresql-psycopg2cffi'
+ - psycopg>=3.0.7 ; extra == 'postgresql-psycopg'
+ - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary'
+ - pymysql ; extra == 'pymysql'
+ - greenlet>=1 ; extra == 'aiomysql'
+ - aiomysql>=0.2.0 ; extra == 'aiomysql'
+ - greenlet>=1 ; extra == 'aioodbc'
+ - aioodbc ; extra == 'aioodbc'
+ - greenlet>=1 ; extra == 'asyncmy'
+ - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy'
+ - greenlet>=1 ; extra == 'aiosqlite'
+ - aiosqlite ; extra == 'aiosqlite'
+ - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
+ - sqlcipher3-binary ; extra == 'sqlcipher'
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: sqlalchemy
+ version: 2.0.45
+ sha256: fe187fc31a54d7fd90352f34e8c008cf3ad5d064d08fedd3de2e8df83eb4a1cf
+ requires_dist:
+ - importlib-metadata ; python_full_version < '3.8'
+ - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'
+ - typing-extensions>=4.6.0
+ - greenlet>=1 ; extra == 'asyncio'
+ - mypy>=0.910 ; extra == 'mypy'
+ - pyodbc ; extra == 'mssql'
+ - pymssql ; extra == 'mssql-pymssql'
+ - pyodbc ; extra == 'mssql-pyodbc'
+ - mysqlclient>=1.4.0 ; extra == 'mysql'
+ - mysql-connector-python ; extra == 'mysql-connector'
+ - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector'
+ - cx-oracle>=8 ; extra == 'oracle'
+ - oracledb>=1.0.1 ; extra == 'oracle-oracledb'
+ - psycopg2>=2.7 ; extra == 'postgresql'
+ - pg8000>=1.29.1 ; extra == 'postgresql-pg8000'
+ - greenlet>=1 ; extra == 'postgresql-asyncpg'
+ - asyncpg ; extra == 'postgresql-asyncpg'
+ - psycopg2-binary ; extra == 'postgresql-psycopg2binary'
+ - psycopg2cffi ; extra == 'postgresql-psycopg2cffi'
+ - psycopg>=3.0.7 ; extra == 'postgresql-psycopg'
+ - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary'
+ - pymysql ; extra == 'pymysql'
+ - greenlet>=1 ; extra == 'aiomysql'
+ - aiomysql>=0.2.0 ; extra == 'aiomysql'
+ - greenlet>=1 ; extra == 'aioodbc'
+ - aioodbc ; extra == 'aioodbc'
+ - greenlet>=1 ; extra == 'asyncmy'
+ - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy'
+ - greenlet>=1 ; extra == 'aiosqlite'
+ - aiosqlite ; extra == 'aiosqlite'
+ - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
+ - sqlcipher3-binary ; extra == 'sqlcipher'
+ requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
+ name: sqlalchemy
+ version: 2.0.45
+ sha256: 5225a288e4c8cc2308dbdd874edad6e7d0fd38eac1e9e5f23503425c8eee20d0
+ requires_dist:
+ - importlib-metadata ; python_full_version < '3.8'
+ - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'
+ - typing-extensions>=4.6.0
+ - greenlet>=1 ; extra == 'asyncio'
+ - mypy>=0.910 ; extra == 'mypy'
+ - pyodbc ; extra == 'mssql'
+ - pymssql ; extra == 'mssql-pymssql'
+ - pyodbc ; extra == 'mssql-pyodbc'
+ - mysqlclient>=1.4.0 ; extra == 'mysql'
+ - mysql-connector-python ; extra == 'mysql-connector'
+ - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector'
+ - cx-oracle>=8 ; extra == 'oracle'
+ - oracledb>=1.0.1 ; extra == 'oracle-oracledb'
+ - psycopg2>=2.7 ; extra == 'postgresql'
+ - pg8000>=1.29.1 ; extra == 'postgresql-pg8000'
+ - greenlet>=1 ; extra == 'postgresql-asyncpg'
+ - asyncpg ; extra == 'postgresql-asyncpg'
+ - psycopg2-binary ; extra == 'postgresql-psycopg2binary'
+ - psycopg2cffi ; extra == 'postgresql-psycopg2cffi'
+ - psycopg>=3.0.7 ; extra == 'postgresql-psycopg'
+ - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary'
+ - pymysql ; extra == 'pymysql'
+ - greenlet>=1 ; extra == 'aiomysql'
+ - aiomysql>=0.2.0 ; extra == 'aiomysql'
+ - greenlet>=1 ; extra == 'aioodbc'
+ - aioodbc ; extra == 'aioodbc'
+ - greenlet>=1 ; extra == 'asyncmy'
+ - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy'
+ - greenlet>=1 ; extra == 'aiosqlite'
+ - aiosqlite ; extra == 'aiosqlite'
+ - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
+ - sqlcipher3-binary ; extra == 'sqlcipher'
+ requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: statsmodels
version: 0.14.6
@@ -2897,6 +3184,22 @@ packages:
- pkg:pypi/tomlkit?source=hash-mapping
size: 38777
timestamp: 1749127286558
+- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
+ name: tqdm
+ version: 4.67.1
+ sha256: 26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2
+ requires_dist:
+ - colorama ; sys_platform == 'win32'
+ - pytest>=6 ; extra == 'dev'
+ - pytest-cov ; extra == 'dev'
+ - pytest-timeout ; extra == 'dev'
+ - pytest-asyncio>=0.24 ; extra == 'dev'
+ - nbval ; extra == 'dev'
+ - requests ; extra == 'discord'
+ - slack-sdk ; extra == 'slack'
+ - requests ; extra == 'telegram'
+ - ipywidgets>=6 ; extra == 'notebook'
+ requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
name: typeguard
version: 4.4.4
@@ -2998,6 +3301,62 @@ packages:
- pytest ; extra == 'dev'
- setuptools ; extra == 'dev'
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/5e/ab/c60fcc137fa685533bb31e721de3ecc88959d393830d59d0204c5cbd2c85/xgboost-3.1.2-py3-none-manylinux_2_28_x86_64.whl
+ name: xgboost
+ version: 3.1.2
+ sha256: 24879ac75c0ee21acae0101f791bc43303f072a86d70fdfc89dae10a0008767f
+ requires_dist:
+ - numpy
+ - nvidia-nccl-cu12 ; platform_machine != 'aarch64' and sys_platform == 'linux'
+ - scipy
+ - dask ; extra == 'dask'
+ - distributed ; extra == 'dask'
+ - pandas ; extra == 'dask'
+ - pandas>=1.2 ; extra == 'pandas'
+ - graphviz ; extra == 'plotting'
+ - matplotlib ; extra == 'plotting'
+ - cloudpickle ; extra == 'pyspark'
+ - pyspark>=3.4 ; extra == 'pyspark'
+ - scikit-learn ; extra == 'pyspark'
+ - scikit-learn ; extra == 'scikit-learn'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/70/2f/5418f4b1deaf0886caf81c5e056299228ac2fc09b965a2dfe5e4496331c8/xgboost-3.1.2-py3-none-manylinux_2_28_aarch64.whl
+ name: xgboost
+ version: 3.1.2
+ sha256: f9b83f39340e5852bbf3e918318e7feb7a2a700ac7e8603f9bc3a06787f0d86b
+ requires_dist:
+ - numpy
+ - scipy
+ - dask ; extra == 'dask'
+ - distributed ; extra == 'dask'
+ - pandas ; extra == 'dask'
+ - pandas>=1.2 ; extra == 'pandas'
+ - graphviz ; extra == 'plotting'
+ - matplotlib ; extra == 'plotting'
+ - cloudpickle ; extra == 'pyspark'
+ - pyspark>=3.4 ; extra == 'pyspark'
+ - scikit-learn ; extra == 'pyspark'
+ - scikit-learn ; extra == 'scikit-learn'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/f4/c6/ed928cb106f56ab73b3f4edb5287c1352251eb9225b5932d3dd5e2803f60/xgboost-3.1.2-py3-none-macosx_12_0_arm64.whl
+ name: xgboost
+ version: 3.1.2
+ sha256: 09690f7430504fcd3b3e62bf826bb1282bb49873b68b07120d2696ab5638df41
+ requires_dist:
+ - numpy
+ - nvidia-nccl-cu12 ; platform_machine != 'aarch64' and sys_platform == 'linux'
+ - scipy
+ - dask ; extra == 'dask'
+ - distributed ; extra == 'dask'
+ - pandas ; extra == 'dask'
+ - pandas>=1.2 ; extra == 'pandas'
+ - graphviz ; extra == 'plotting'
+ - matplotlib ; extra == 'plotting'
+ - cloudpickle ; extra == 'pyspark'
+ - pyspark>=3.4 ; extra == 'pyspark'
+ - scikit-learn ; extra == 'pyspark'
+ - scikit-learn ; extra == 'scikit-learn'
+ requires_python: '>=3.10'
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae
md5: 30cd29cb87d819caead4d55184c1d115
diff --git a/pyproject.toml b/pyproject.toml
index 45ccd2b..e1687b9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,7 +20,7 @@ dependencies = [
"joblib>=1.5.3,<2",
"statsmodels>=0.14.6,<0.15",
"typer>=0.20.0,<0.21",
- "pandera>=0.27.1,<0.28",
+ "pandera>=0.27.1,<0.28", "xgboost>=3.1.2,<4", "optuna>=4.6.0,<5",
]
[build-system]
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index a997c7a..31e587e 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -41,50 +41,30 @@ def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.Da
return masked_ratios
-def build_multi_output_nn(input_dim: int, n_neurons: int):
- """Build a multi-output neural network for regression and classification."""
- inputs = layers.Input(shape=(input_dim,))
- x = layers.Dense(n_neurons, activation="relu")(inputs)
- x = layers.Dense(n_neurons // 2, activation="relu")(x)
- # Head 1: Regression
- reg_out = layers.Dense(1, activation="linear", name="reg_output")(x)
-
- # Head 2: Classification
- class_out = layers.Dense(1, activation="sigmoid", name="class_output")(x)
-
- nn = Model(inputs=inputs, outputs=[reg_out, class_out])
- nn.compile(
- optimizer="adam",
- loss={"reg_output": "mse", "class_output": "binary_crossentropy"},
- loss_weights={"reg_output": 1.0, "class_output": 1.0},
- )
- return nn
-
-
-class PCALayer(layers.Layer):
- def __init__(self, pca, **kwargs):
- super(
- PCALayer,
- self,
- ).__init__(**kwargs)
- # Convert Scikit-Learn attributes to TensorFlow constants
- self.components = tf.constant(pca.components_.T, dtype=tf.float32)
-
- def call(self, inputs):
- # PCA: Matrix multiplication with components
- pca_data = tf.matmul(inputs, self.components)
- return pca_data
-
-
def build_ensemble(n_feat: int, pca: PCA, models: list[Model]) -> Model:
"""
Build an ensemble model that averages predictions from multiple fold models.
Each fold model is assumed to have two outputs: regression and classification.
"""
+
# Add input layer
ensemble_input = layers.Input(shape=(n_feat,), name="input")
# Add PCA layer
+ class PCALayer(layers.Layer):
+ def __init__(self, pca, **kwargs):
+ super(
+ PCALayer,
+ self,
+ ).__init__(**kwargs)
+ # Convert Scikit-Learn attributes to TensorFlow constants
+ self.components = tf.constant(pca.components_.T, dtype=tf.float32)
+
+ def call(self, inputs):
+ # PCA: Matrix multiplication with components
+ pca_data = tf.matmul(inputs, self.components)
+ return pca_data
+
pca_feat = PCALayer(pca, name="pca")(ensemble_input)
# Add each fold model as a sub-network
@@ -105,7 +85,9 @@ def build_ensemble(n_feat: int, pca: PCA, models: list[Model]) -> Model:
# Build and return ensemble model
return Model(
- inputs=ensemble_input, outputs=[avg_reg_output, avg_class_output], name="PREFACE_model"
+ inputs=ensemble_input,
+ outputs=[avg_reg_output, avg_class_output],
+ name="PREFACE_model",
)
@@ -257,6 +239,10 @@ def plot_regression_performance(
}
+def plot_classification_performance():
+ pass
+
+
def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
"""
Fit robust linear model (RLM) and return intercept and slope.
@@ -305,9 +291,7 @@ def plot_ffx(
)
ax.legend()
ax = axes[1]
- y_values_corrected = (
- (y_values - intercept) / slope if slope != 0 else y_values
- )
+ y_values_corrected = (y_values - intercept) / slope if slope != 0 else y_values
ax.scatter(x_values, y_values_corrected, s=10, c="black", alpha=0.6)
ax.set_xlabel("FF (%)")
ax.set_ylabel("FFX (%)")
@@ -322,4 +306,3 @@ def plot_ffx(
plt.tight_layout()
plt.savefig(out_dir_path / "FFX.png", dpi=300)
plt.close()
-
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
new file mode 100644
index 0000000..ab12a3d
--- /dev/null
+++ b/src/preface/lib/neural.py
@@ -0,0 +1,138 @@
+from pathlib import Path
+
+import numpy as np
+import numpy.typing as npt
+import optuna
+from sklearn.model_selection import KFold
+from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
+from tensorflow.keras import ( # pylint: disable=no-name-in-module,import-error # type: ignore
+ Model,
+ layers,
+)
+
+
+def neural_tune(features: npt.NDArray, targets: npt.NDArray, outdir: Path) -> dict:
+ def objective(trial) -> float:
+ params = {
+ "n_layers": trial.suggest_int("n_layers", 1, 3),
+ "hidden_size": trial.suggest_int("hidden_size", 16, 128, step=32),
+ "learning_rate": trial.suggest_float("learning_rate", 1e-4, 1e-2, log=True),
+ "dropout_rate": trial.suggest_float("dropout_rate", 0.1, 0.5, step=0.1),
+ }
+
+ # Internal split for the tuner
+ kf_internal = KFold(n_splits=3, shuffle=True)
+ scores = []
+
+ for t_idx, v_idx in kf_internal.split(features):
+ model = multi_output_nn(
+ input_dim=features.shape[1],
+ n_layers=params["n_layers"],
+ hidden_size=params["hidden_size"],
+ learning_rate=params["learning_rate"],
+ dropout_rate=params["dropout_rate"],
+ )
+ history = model.fit(
+ features[t_idx],
+ targets[t_idx],
+ validation_data=(features[v_idx], targets[v_idx]),
+ epochs=50,
+ batch_size=16,
+ callbacks=[
+ optuna.integration.TFKerasPruningCallback(trial, "val_loss")
+ ],
+ )
+ scores.append(min((history.history["val_loss"])))
+
+ return np.mean(scores).astype(float)
+
+ study = optuna.create_study(
+ direction="minimize", pruner=optuna.pruners.MedianPruner()
+ )
+ study.optimize(objective, n_trials=30)
+
+ optuna.visualization.plot_optimization_history(study).savefig(
+ outdir / "neural_tuning_history.png"
+ )
+ return study.best_params
+
+
+def multi_output_nn(
+ input_dim: int,
+ n_layers: int,
+ hidden_size: int,
+ learning_rate: float,
+ dropout_rate: float,
+) -> Model:
+ x = layers.Input(shape=(input_dim,))
+ for _ in range(n_layers):
+ x = layers.Dense(hidden_size, activation="relu")(x)
+ x = layers.Dropout(dropout_rate)(x)
+
+ # Head 1: Regression
+ reg_out = layers.Dense(1, activation="linear", name="reg_output")(x)
+ # Head 2: Classification
+ class_out = layers.Dense(1, activation="sigmoid", name="class_output")(x)
+
+ nn = Model(inputs=x, outputs=[reg_out, class_out])
+
+ nn.compile(
+ optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
+ loss={"reg_output": "mse", "class_output": "binary_crossentropy"},
+ loss_weights={"reg_output": 1.0, "class_output": 1.0},
+ )
+ return nn
+
+
+def neural_fit(
+ x_train: npt.NDArray,
+ x_test: npt.NDArray,
+ y_train_reg: npt.NDArray,
+ y_train_class: npt.NDArray,
+ y_test_reg: npt.NDArray,
+ y_test_class: npt.NDArray,
+ input_dim: int,
+ params: dict,
+) -> tuple[Model, dict]:
+ """Build a multi-output neural network for regression and classification."""
+ # default parameters
+ nn_default_params = {
+ "n_layers": 3,
+ "hidden_size": 64,
+ "learning_rate": 1e-3,
+ "dropout_rate": 0.3,
+ }
+
+ # Early stopping callback
+ early_stop = keras.callbacks.EarlyStopping(
+ monitor="val_loss", patience=5, restore_best_weights=True
+ )
+
+ # Create model
+ model = multi_output_nn(input_dim=input_dim, **{**nn_default_params, **params})
+
+ # Fit model
+ model.fit(
+ x_train,
+ {"reg_output": y_train_reg, "class_output": y_train_class},
+ validation_data=(
+ x_test,
+ {"reg_output": y_test_reg, "class_output": y_test_class},
+ ),
+ epochs=100,
+ batch_size=32,
+ verbose=1,
+ callbacks=[early_stop],
+ )
+
+ # Evaluate
+ predictions = model.predict(x_test)
+ reg_preds = predictions[0].flatten()
+ class_probs = predictions[1].flatten()
+ class_preds = (class_probs >= 0.5).astype(int)
+
+ return model, {
+ "regression_predictions": reg_preds,
+ "class_probabilities": class_probs,
+ "class_predictions": class_preds,
+ }
diff --git a/src/preface/lib/schemas.py b/src/preface/lib/schemas.py
index 201618b..2b5520d 100644
--- a/src/preface/lib/schemas.py
+++ b/src/preface/lib/schemas.py
@@ -5,8 +5,9 @@ class SampleSchema(pa.DataFrameSchema):
"""
Sample schema for samplesheet entries.
"""
+
ff = pa.Column(float, checks=[pa.Check.ge(0.0), pa.Check.le(1.0)], nullable=True)
- filepath = pa.Column(str, checks=[pa.Check.str_matches(r'.+\.bed$')])
+ filepath = pa.Column(str, checks=[pa.Check.str_matches(r".+\.bed$")])
id = pa.Column(str)
sex = pa.Column(str, checks=pa.Check.isin(["M", "F"]))
@@ -15,7 +16,10 @@ class SampleDataSchema(pa.DataFrameSchema):
"""
Sample data model for samplesheet entries with optional fetal fraction.
"""
- chr = pa.Column(str, checks=pa.Check.str_matches(r'^(chr)?([1-9]|1[0-9]|2[0-2]|X|Y|MT)$'))
+
+ chr = pa.Column(
+ str, checks=pa.Check.str_matches(r"^(chr)?([1-9]|1[0-9]|2[0-2]|X|Y|MT)$")
+ )
start = pa.Column(int, checks=pa.Check.ge(0), coerce=True)
end = pa.Column(int, checks=pa.Check.ge(0), coerce=True)
ratio = pa.Column(float, checks=[pa.Check.ge(0.0), pa.Check.le(1.0)], nullable=True)
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
new file mode 100644
index 0000000..2f7734c
--- /dev/null
+++ b/src/preface/lib/xgboost.py
@@ -0,0 +1,88 @@
+from pathlib import Path
+
+import numpy as np
+import numpy.typing as npt
+import optuna
+from sklearn.metrics import mean_squared_error
+from sklearn.model_selection import KFold
+from tensorflow.keras import ( # type: ignore # pylint: disable=no-name-in-module,import-error
+ Model,
+)
+from xgboost import XGBRegressor
+
+
+def xgboost_tune(features: npt.NDArray, targets: npt.NDArray, outdir: Path) -> dict:
+ def objective(trial) -> float:
+ params = {
+ # number of boosting rounds
+ "n_estimators": trial.suggest_int("n_estimators", 100, 800),
+ # maximum depth of each tree
+ "max_depth": trial.suggest_int("max_depth", 3, 8),
+ "learning_rate": trial.suggest_float("learning_rate", 0.01, 0.1, log=True),
+ # sampling ratios
+ "subsample": trial.suggest_float("subsample", 0.6, 1.0),
+ "colsample_bytree": trial.suggest_float("colsample_bytree", 0.6, 1.0),
+ "tree_method": "hist",
+ "multi_strategy": "multi_output_tree",
+ # random state for reproducibility
+ "random_state": 42,
+ }
+
+ # Internal split for the tuner
+ kf_internal = KFold(n_splits=3, shuffle=True)
+ scores = []
+
+ for t_idx, v_idx in kf_internal.split(features):
+ model = XGBRegressor(**params)
+ model.fit(features[t_idx], targets[t_idx])
+ preds = model.predict(features[v_idx])
+ scores.append(mean_squared_error(targets[v_idx], preds))
+ return np.mean(scores).astype(float)
+
+ study = optuna.create_study(direction="minimize")
+ study.optimize(objective, n_trials=30)
+
+ optuna.visualization.plot_optimization_history(study).savefig(
+ outdir / "xgboost_tuning_history.png"
+ )
+ return study.best_params
+
+
+def xgboost_fit(
+ x_train: npt.NDArray,
+ x_test: npt.NDArray,
+ y_train: npt.NDArray,
+ y_test: npt.NDArray,
+ params: dict,
+) -> tuple[Model, dict]:
+ """Build a multi-output xgboost model for regression and classification."""
+ # Training parameters
+ xgb_default_params = {
+ "tree_method": "hist",
+ "multi_strategy": "multi_output_tree",
+ "n_estimators": 100,
+ "max_depth": 6,
+ "learning_rate": 0.1,
+ "random_state": 42,
+ "early_stopping_rounds": 10,
+ }
+
+ # Create model
+ model = XGBRegressor(
+ **{**xgb_default_params, **params} # Merge default and tuned parameters
+ )
+
+ # Fit model
+ model.fit(x_train, y_train, eval_set=[(x_test, y_test)], verbose=False)
+
+ # Evaluate
+ preds = model.predict(x_test)
+ reg_preds = preds[:, 0]
+ class_probs = preds[:, 1]
+ class_preds = (class_probs > 0.5).astype(int)
+
+ return model, {
+ "regression_predictions": reg_preds,
+ "class_probabilities": class_probs,
+ "class_predictions": class_preds,
+ }
diff --git a/src/preface/predict.py b/src/preface/predict.py
index 07a5c70..7ce4711 100644
--- a/src/preface/predict.py
+++ b/src/preface/predict.py
@@ -2,107 +2,80 @@
Predict module for PREFACE.
"""
-import os
-import json
-from typing import Optional, Union
-import numpy as np
import pandas as pd
-import joblib
import typer
-from sklearn.linear_model import LinearRegression
-from tensorflow import keras # pylint: disable=no-name-in-module,import-error
+from tensorflow.keras import load_model # pylint: disable=no-name-in-module,import-error # type: ignore
+from preface.lib.schemas import SampleDataSchema
+from preface.lib.functions import preprocess_ratios
def preface_predict(
infile: str = typer.Option(..., "--infile", help="Path to input BED file"),
- model_path_base: str = typer.Option(
- ..., "--model", help="Path to model (directory or model_meta.pkl)"
- ),
- json_output: Optional[str] = typer.Option(
- None,
- "--json",
- help="Output JSON. If filename provided, writes to file. Pass 'stdout' for console output.",
- ),
+ model_path: str = typer.Option(..., "--model", help="Path to model"),
) -> None:
"""
Predict using model.
"""
- if os.path.isdir(model_path_base):
- meta_path = os.path.join(model_path_base, "model_meta.pkl")
- else:
- meta_path = model_path_base
-
- if not os.path.exists(meta_path):
- root, _ = os.path.splitext(model_path_base)
- if os.path.exists(root + ".pkl"):
- meta_path = root + ".pkl"
- else:
- typer.echo(f"The file '{meta_path}' does not exist.")
- raise typer.Exit(code=1)
-
- model_data = joblib.load(meta_path)
-
- n_feat = model_data["n_feat"]
- mean_features = model_data["mean_features"]
- possible_features = model_data["possible_features"]
- pca = model_data["pca"]
- is_olm = model_data["is_olm"]
- the_intercept = model_data["the_intercept"]
- the_slope = model_data["the_slope"]
- # Variable names in the pickle are fixed, but we map them to snake_case locals
- intercept_x = model_data["the_intercept_X"]
- slope_x = model_data["the_slope_X"]
-
- dir_path = os.path.dirname(meta_path)
- model: Union[LinearRegression, keras.Model]
- if is_olm:
- model = joblib.load(os.path.join(dir_path, "model_weights.pkl"))
- else:
- model = keras.models.load_model(os.path.join(dir_path, "model_weights.keras"))
-
- bin_table = pd.read_csv(infile, sep="\t")
-
- x_bins = bin_table[bin_table["chr"] == "X"]
- x_ratio: float
- if len(x_bins) > 0:
- x_ratio = float(2 ** np.mean(x_bins["ratio"].dropna()))
- else:
- x_ratio = float(np.nan)
-
- ffx: float = (x_ratio - intercept_x) / slope_x
-
- bin_table["feat_id"] = (
- bin_table["chr"].astype(str)
- + ":"
- + bin_table["start"].astype(str)
- + "-"
- + bin_table["end"].astype(str)
- )
-
- ratio_map = bin_table.set_index("feat_id")["ratio"]
- features = ratio_map.reindex(possible_features)
- features = features.fillna(mean_features)
-
- features_array = features.values.reshape(1, -1)
-
- projected_ratio = pca.transform(features_array)[:, :n_feat]
-
- prediction: float
- if is_olm:
- prediction = float(model.predict(projected_ratio)[0])
- else:
- prediction = float(model.predict(projected_ratio).flatten()[0])
-
- prediction = the_intercept + the_slope * prediction
-
- json_dict = {"FFX": ffx / 100, "PREFACE": prediction / 100}
-
- if json_output:
- if json_output not in ("stdout", ""):
- with open(json_output, "w", encoding="utf-8") as f:
- json.dump(json_dict, f)
- else:
- typer.echo(json.dumps(json_dict))
- else:
- typer.echo(f"FFX = {ffx:.4g}%")
- typer.echo(f"PREFACE = {prediction:.4g}%")
+
+ # Load model
+ preface_model = load_model(model_path)
+ ratios = pd.read_csv(infile, sep="\t")
+
+ # Validate input data
+ try:
+ SampleDataSchema().validate(ratios)
+ except Exception as e:
+ typer.echo(f"Validation error: {e}")
+ raise
+
+ # Preprocess ratios
+ preprocessed_ratios = preprocess_ratios(ratios, exclude_chrs=[])
+
+ # x_bins = ratios[ratios["chr"] == "X"]
+ # x_ratio: float
+ # if len(x_bins) > 0:
+ # x_ratio = float(2 ** np.mean(x_bins["ratio"].dropna()))
+ # else:
+ # x_ratio = float(np.nan)
+
+ ff_pred, sex_pred = preface_model.predict(preprocessed_ratios.values)
+ typer.echo(f"FF = {ff_pred:.4g}%")
+ typer.echo(f"Sex = {sex_pred}")
+
+ # ffx: float = (x_ratio - intercept_x) / slope_x
+
+ # bin_table["feat_id"] = (
+ # bin_table["chr"].astype(str)
+ # + ":"
+ # + bin_table["start"].astype(str)
+ # + "-"
+ # + bin_table["end"].astype(str)
+ # )
+
+ # ratio_map = bin_table.set_index("feat_id")["ratio"]
+ # features = ratio_map.reindex(possible_features)
+ # features = features.fillna(mean_features)
+
+ # features_array = features.values.reshape(1, -1)
+
+ # projected_ratio = pca.transform(features_array)[:, :n_feat]
+
+ # prediction: float
+ # if is_olm:
+ # prediction = float(model.predict(projected_ratio)[0])
+ # else:
+ # prediction = float(model.predict(projected_ratio).flatten()[0])
+
+ # prediction = the_intercept + the_slope * prediction
+
+ # json_dict = {"FFX": ffx / 100, "PREFACE": prediction / 100}
+
+ # if json_output:
+ # if json_output not in ("stdout", ""):
+ # with open(json_output, "w", encoding="utf-8") as f:
+ # json.dump(json_dict, f)
+ # else:
+ # typer.echo(json.dumps(json_dict))
+ # else:
+ # typer.echo(f"FFX = {ffx:.4g}%")
+ # typer.echo(f"PREFACE = {prediction:.4g}%")
diff --git a/src/preface/preface.py b/src/preface/preface.py
index d852fb7..03fb17a 100644
--- a/src/preface/preface.py
+++ b/src/preface/preface.py
@@ -3,25 +3,21 @@
"""
import typer
-import importlib.metadata
-
+from preface import __version__
from preface.predict import preface_predict
from preface.train import preface_train
-from preface.utils.npz_to_parquet import npz_to_parquet
from preface.utils.ffy import wisecondorx_ffy
-from preface import __version__
+from preface.utils.npz_to_parquet import npz_to_parquet
# Version
VERSION: str = __version__
-AUTHORS: str = importlib.metadata.metadata("preface")["authors"]
-
-print(AUTHORS)
# Initialize Typer app
app = typer.Typer(help="PREFACE - PREdict FetAl ComponEnt")
app.command(name="predict")(preface_predict)
app.command(name="train")(preface_train)
+app.command(name="version")(lambda: typer.echo(f"PREFACE version {VERSION}"))
# Utilities group
utils_app = typer.Typer(help="Utility scripts")
diff --git a/src/preface/train.py b/src/preface/train.py
index 1ae804a..441821b 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -6,6 +6,7 @@
import time
from pathlib import Path
+from enum import Enum
import pandas as pd
import typer
from pandera.errors import SchemaError
@@ -19,33 +20,65 @@
from preface.lib.functions import (
build_ensemble,
- build_multi_output_nn,
plot_regression_performance,
+ plot_classification_performance,
preprocess_ratios,
)
+from preface.lib.xgboost import xgboost_tune, xgboost_fit
+from preface.lib.neural import neural_tune, neural_fit
from preface.lib.schemas import SampleDataSchema, SampleSchema
# Constants
-EXCLUDE_CHRS: list[str] = ['13', '18', '21', 'X', 'Y']
+EXCLUDE_CHRS: list[str] = ["13", "18", "21", "X", "Y"]
+
+
+class ModelOptions(Enum):
+ NEURAL = "neural"
+ XGBOOST = "xgboost"
+
+
+class ModeOptions(Enum):
+ TRAIN = "train"
+ TUNE = "tune"
def preface_train(
- samplesheet: Path = typer.Option(..., "--samplesheet", help="Path to samplesheet file"),
- out_dir: Path = typer.Option(..., "--outdir", help="Output directory"),
- n_feat: int = typer.Option(50, "--nfeat", help="Number of features (PCA components)"),
- n_folds: int = typer.Option(5, "--nfolds", help="Number of folds for cross-validation"),
- n_neurons: int = typer.Option(2, "--neurons", help="Number of initial neurons in neural network"),
- exclude_chrs: list[str] = typer.Option(EXCLUDE_CHRS, "--exclude-chrs", help="Chromosomes to exclude from training"),
- impute: bool = typer.Option(False, "--impute", help="Impute missing values instead of assuming zero")
+ samplesheet: Path = typer.Option(
+ ..., "--samplesheet", help="Path to samplesheet file"
+ ),
+ out_dir: Path = typer.Option(os.getcwd(), "--outdir", help="Output directory"),
+ # Data handling
+ impute: bool = typer.Option(
+ False, "--impute", help="Impute missing values instead of assuming zero"
+ ),
+ exclude_chrs: list[str] = typer.Option(
+ EXCLUDE_CHRS, "--exclude-chrs", help="Chromosomes to exclude from training"
+ ),
+ # cross validation options
+ n_folds: int = typer.Option(
+ 5, "--nfolds", help="Number of folds for cross-validation"
+ ),
+ # PCA options
+ n_feat: int = typer.Option(
+ 50, "--nfeat", help="Number of features (PCA components)"
+ ),
+ # Mode options
+ tune: bool = typer.Option(
+ False, "--tune", help="Enable automatic hyperparameter tuning"
+ ),
+ # Model options
+ model: ModelOptions = typer.Option(
+ ModelOptions.NEURAL, "--model", help="Type of model to train"
+ ),
) -> None:
"""
- Train the PREFACE model.
+ Train and optionally tune the PREFACE model.
"""
start_time: float = time.time()
# Load samplesheet
samplesheet_data: pd.DataFrame = pd.read_csv(
- samplesheet, comment='#', dtype={'sex': str, 'ID': str}, index_col='ID'
+ samplesheet, comment="#", dtype={"sex": str, "ID": str}, index_col="ID"
)
# Validate samplesheet
@@ -75,16 +108,26 @@ def preface_train(
# parse data
for _, sample in samplesheet_data.iterrows():
- if not Path(sample['filepath']).exists() or not Path(sample['filepath']).is_file():
+ if (
+ not Path(sample["filepath"]).exists()
+ or not Path(sample["filepath"]).is_file()
+ ):
typer.echo(f"Error: File '{sample['filepath']}' does not exist.")
raise typer.Exit(code=1)
# load ratios (bed format)
- ratios = pd.read_csv(sample['filepath'], dtype={'chr': str, 'start': int, 'end': int, 'ratio': float}, sep='\t', header=0)
+ ratios = pd.read_csv(
+ sample["filepath"],
+ dtype={"chr": str, "start": int, "end": int, "ratio": float},
+ sep="\t",
+ header=0,
+ )
# validate ratios
try:
sample_data_schema.validate(ratios)
except SchemaError as e:
- typer.echo(f"Error validating sample data for file {sample['filepath']}: {e}")
+ typer.echo(
+ f"Error validating sample data for file {sample['filepath']}: {e}"
+ )
raise typer.Exit(code=1)
# check number of bins consistency
@@ -99,9 +142,9 @@ def preface_train(
masked_ratios = preprocess_ratios(ratios, exclude_chrs)
# add sample metadata columns to transposed ratios
- masked_ratios['id'] = sample['ID']
- masked_ratios['sex'] = sample['sex']
- masked_ratios['ff'] = sample['FF']
+ masked_ratios["id"] = sample["ID"]
+ masked_ratios["sex"] = sample["sex"]
+ masked_ratios["ff"] = sample["FF"]
# add to list
ratios_list.append(masked_ratios)
@@ -111,7 +154,7 @@ def preface_train(
ratios_per_sample: pd.DataFrame = pd.concat(ratios_list, axis=0)
# set index to ID column
- ratios_per_sample = ratios_per_sample.set_index('id')
+ ratios_per_sample = ratios_per_sample.set_index("id")
typer.echo("Creating training frame...")
@@ -131,12 +174,14 @@ def preface_train(
typer.echo("Imputing missing values using MICE...")
- imputer = IterativeImputer(random_state=42, max_iter=10, initial_strategy='mean')
+ imputer = IterativeImputer(
+ random_state=42, max_iter=10, initial_strategy="mean"
+ )
training_df_array = imputer.fit_transform(ratios_per_sample)
ratios_per_sample = pd.DataFrame(
training_df_array,
index=ratios_per_sample.index,
- columns=ratios_per_sample.columns
+ columns=ratios_per_sample.columns,
)
# Option 2: Assume missing values are zero (no change)
else:
@@ -144,24 +189,29 @@ def preface_train(
ratios_per_sample = ratios_per_sample.fillna(0.0)
# Split into features and labels
- x_all: pd.DataFrame = ratios_per_sample.drop(columns=['sex', 'ff'])
+ x_all: pd.DataFrame = ratios_per_sample.drop(columns=["sex", "ff"])
+ y_all: pd.DataFrame = ratios_per_sample[["sex", "ff"]]
# labels for regression (fetal fraction)
- y_ff_all = ratios_per_sample['ff']
+ y_ff_all = y_all["ff"]
# labels for classification (sex)
- y_sex_all = (
- ratios_per_sample['sex']
- .map({"M": 1, "F": 0})
- .astype(float)
- .values
- )
+ y_sex_all = y_all["sex"].map({"M": 1, "F": 0})
# Reduce dimensionality with PCA
global_pca = PCA(n_components=n_feat)
x_all_pca = global_pca.fit_transform(x_all)
- # Set up training
+ params = {}
+ if tune:
+ # Enable hyperparameter tuning
+ typer.echo("Tuning hyperparameters...")
+ if model == ModelOptions.NEURAL:
+ params = neural_tune(x_all_pca, y_all.to_numpy(), out_dir)
+ elif model == ModelOptions.XGBOOST:
+ params = xgboost_tune(x_all_pca, y_all.to_numpy(), out_dir)
+
+ # Set up training (k-fold cross-validation)
# Create directory to store fold metrics
- os.makedirs(out_dir / 'training_folds', exist_ok=True)
+ os.makedirs(out_dir / "training_folds", exist_ok=True)
fold_metrics = []
fold_models: list[keras.Model] = []
@@ -172,48 +222,36 @@ def preface_train(
# split into train and test sets
x_train, x_test = x_all_pca[train_idx], x_all_pca[test_idx]
- y_ff_train, y_ff_test = y_ff_all[train_idx], y_ff_all[test_idx]
- y_sex_train, y_sex_test = y_sex_all[train_idx], y_sex_all[test_idx]
-
- # Create new model instance
- model = build_multi_output_nn(input_dim=n_feat, n_neurons=n_neurons)
+ y_train, y_test = y_all.iloc[train_idx], y_all.iloc[test_idx]
+ y_train_reg, y_test_reg = y_ff_all[train_idx], y_ff_all[test_idx]
+ y_train_class, y_test_class = y_sex_all[train_idx], y_sex_all[test_idx]
# Train
typer.echo(f"Training fold {fold}...")
- # Early stopping callback
- early_stop = keras.callbacks.EarlyStopping(
- monitor='val_loss',
- patience=5,
- restore_best_weights=True
- )
- # Fit model
- model.fit(
- x_train,
- {"reg_output": y_ff_train, "class_output": y_sex_train},
- validation_data=(
+ if model == ModelOptions.NEURAL:
+ model, predictions = neural_fit(
+ x_train,
x_test,
- {"reg_output": y_ff_test, "class_output": y_sex_test},
- ),
- epochs=100,
- batch_size=32,
- verbose=1,
- callbacks=[early_stop],
- )
+ y_train_reg.to_numpy(),
+ y_train_class.to_numpy(),
+ y_test_reg.to_numpy(),
+ y_test_class.to_numpy(),
+ n_feat,
+ params,
+ )
+ elif model == ModelOptions.XGBOOST:
+ model, predictions = xgboost_fit(
+ x_train, x_test, y_train.to_numpy(), y_test.to_numpy(), params
+ )
# Save fold model
- model.save(out_dir / 'training_folds' / f'fold_{fold}.keras')
+ model.save(out_dir / "training_folds" / f"fold_{fold}.keras") # type: ignore
fold_models.append(model)
- # Evaluate
- predictions = model.predict(x_test)
- y_ff_pred = predictions[0].flatten()
- class_pred_probs = predictions[1].flatten()
- class_pred = (class_pred_probs >= 0.5).astype(int)
-
# Plot regression performance
reg_perf = plot_regression_performance(
- y_ff_pred,
- y_ff_test.to_numpy(),
+ predictions["regression_predictions"],
+ y_test_reg.to_numpy(),
global_pca.explained_variance_ratio_,
n_feat,
"PREFACE (%)",
@@ -221,31 +259,34 @@ def preface_train(
out_dir / "training_folds" / f"fold_{fold}_regression.png",
)
- # Calculate metrics
+ # Plot classification performance
+ plot_classification_performance()
+
+ # return metrics
metrics: dict = {
# fold number
- 'fold': fold,
+ "fold": fold,
# regression metrics
- 'ff_mae': mean_absolute_error(y_ff_test, y_ff_pred),
- 'ff_r2': r2_score(y_ff_test, y_ff_pred),
- 'ff_intercept': reg_perf['intercept'],
- 'ff_slope': reg_perf['slope'],
+ "ff_mae": mean_absolute_error(
+ y_test_reg, predictions["regression_predictions"]
+ ),
+ "ff_r2": r2_score(y_test_reg, predictions["regression_predictions"]),
+ "ff_intercept": reg_perf["intercept"],
+ "ff_slope": reg_perf["slope"],
# classification metrics
- 'sex_f1': f1_score(y_sex_test, class_pred), # type: ignore
- 'sex_auc': roc_auc_score(y_sex_test, class_pred_probs) # type: ignore
+ "sex_f1": f1_score(y_test_class, predictions["class_predictions"]),
+ "sex_auc": roc_auc_score(y_test_class, predictions["class_probabilities"]),
}
fold_metrics.append(metrics)
# Save fold metrics to a DataFrame
fold_metrics_df = pd.DataFrame(fold_metrics)
- fold_metrics_df.to_csv(
- out_dir / 'training_fold_metrics.csv', index=False
- )
+ fold_metrics_df.to_csv(out_dir / "training_fold_metrics.csv", index=False)
# Build ensemble model from fold models
typer.echo("Building ensemble model from fold models...")
ensemble_model = build_ensemble(len(x_all.columns), global_pca, fold_models)
- ensemble_model.save(out_dir / 'PREFACE')
+ ensemble_model.save(out_dir / "PREFACE")
# Final evaluation on all training data
typer.echo("Evaluating final model on all training data...")
@@ -255,14 +296,12 @@ def preface_train(
y_ff_all.to_numpy(),
global_pca.explained_variance_ratio_,
n_feat,
- 'PREFACE (%)',
- 'FF (%)',
- out_dir / 'overall_performance.png'
+ "PREFACE (%)",
+ "FF (%)",
+ out_dir / "overall_performance.png",
)
- with open(
- out_dir / 'training_statistics.txt', 'w', encoding='utf-8'
- ) as f:
+ with open(out_dir / "training_statistics.txt", "w", encoding="utf-8") as f:
f.write(
f"""PREFACE - PREdict FetAl ComponEnt
Training time: {time.time() - start_time:.0f} seconds
diff --git a/src/preface/utils/ffy.py b/src/preface/utils/ffy.py
index 1710e63..42f4cb3 100644
--- a/src/preface/utils/ffy.py
+++ b/src/preface/utils/ffy.py
@@ -9,9 +9,15 @@
def wisecondorx_ffy(
wisecondorx_npz: Path = typer.Argument(
- ..., help="Path to WisecondorX NPZ file", exists=True, file_okay=True, dir_okay=False
+ ...,
+ help="Path to WisecondorX NPZ file",
+ exists=True,
+ file_okay=True,
+ dir_okay=False,
+ ),
+ sex_cutoff: float = typer.Option(
+ 0.2, "--sex-cutoff", help="Cutoff for sex determination"
),
- sex_cutoff: float = typer.Option(0.2, "--sex-cutoff", help="Cutoff for sex determination"),
) -> dict:
"""
Calculate fetal fraction from Y chromosome (FFY) using WisecondorX output.
diff --git a/src/preface/utils/npz_to_parquet.py b/src/preface/utils/npz_to_parquet.py
index 5d0b17c..2b2d26d 100644
--- a/src/preface/utils/npz_to_parquet.py
+++ b/src/preface/utils/npz_to_parquet.py
@@ -71,7 +71,9 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
def npz_to_parquet(
- npz_files: List[str] = typer.Argument(..., help="One or more .npz files to convert."),
+ npz_files: List[str] = typer.Argument(
+ ..., help="One or more .npz files to convert."
+ ),
output_dir: str = typer.Option(
".", "-o", "--output-dir", help="Directory to save the output Parquet files."
),
From 3f6c763c3ae3843abc62356aa898375690da336c Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sat, 27 Dec 2025 16:22:18 +0100
Subject: [PATCH 10/50] fix SettingWithCopyWarning in functions.py
---
src/preface/lib/functions.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index 31e587e..e74cf55 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -26,10 +26,14 @@ def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.Da
# santize chr column
ratios_df["chr"] = ratios_df["chr"].astype(str).str.replace("chr", "", regex=False)
# exclude chromosomes
- masked_ratios = ratios_df[~ratios_df["chr"].isin(exclude_chrs)]
+ masked_ratios = ratios_df[~ratios_df["chr"].isin(exclude_chrs)].copy()
# add region column
masked_ratios["region"] = (
- f"{masked_ratios['chr']}:{masked_ratios['start']}-{masked_ratios['end']}"
+ masked_ratios["chr"]
+ + ":"
+ + masked_ratios["start"].astype(str)
+ + "-"
+ + masked_ratios["end"].astype(str)
)
# drop chr, start, end columns
masked_ratios = masked_ratios.drop(columns=["chr", "start", "end"])
From 8e8abbc04cdb761029c0b00b15d94e3c976c5b34 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sat, 27 Dec 2025 17:42:37 +0100
Subject: [PATCH 11/50] drop schema validation, add logging
---
.gitignore | 1 +
pixi.lock | 523 +++++++++++++++++++++++++++-
src/preface/lib/functions.py | 23 +-
src/preface/lib/schemas.py | 25 --
src/preface/lib/xgboost.py | 1 -
src/preface/predict.py | 27 +-
src/preface/preface.py | 33 +-
src/preface/train.py | 67 ++--
src/preface/utils/npz_to_parquet.py | 20 +-
9 files changed, 597 insertions(+), 123 deletions(-)
delete mode 100644 src/preface/lib/schemas.py
diff --git a/.gitignore b/.gitignore
index 6609d58..2b8a5bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@ data/
*.egg-info
__pycache__/
.gemini/
+*.ipynb
# pixi environments
.pixi/*
!.pixi/config.toml
diff --git a/pixi.lock b/pixi.lock
index 5710509..414b141 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -45,13 +45,18 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
@@ -60,7 +65,13 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
@@ -69,10 +80,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
@@ -81,9 +94,15 @@ environments:
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/12/ff/e93136587c00a543f4bc768b157fac2c47cd77b180d4f4e5c6efb6ea53a2/psutil-7.2.0-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
@@ -91,6 +110,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -99,13 +119,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
@@ -113,6 +136,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
@@ -154,13 +178,18 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
@@ -169,7 +198,13 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
@@ -178,10 +213,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
@@ -189,9 +226,15 @@ environments:
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/b8/dd/4c2de9c3827c892599d277a69d2224136800870a8a88a80981de905de28d/psutil-7.2.0-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
@@ -199,6 +242,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
@@ -207,13 +251,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
@@ -221,6 +268,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
@@ -256,13 +304,19 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
@@ -270,7 +324,13 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
@@ -279,10 +339,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
@@ -290,9 +352,15 @@ environments:
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/10/a1/c75feb480f60cd768fb6ed00ac362a16a33e5076ec8475a22d8162fb2659/psutil-7.2.0-cp36-abi3-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
@@ -300,6 +368,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
@@ -308,13 +377,16 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
@@ -322,6 +394,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
@@ -385,6 +458,11 @@ packages:
requires_dist:
- typing-extensions>=4.0.0 ; python_full_version < '3.9'
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
+ name: appnope
+ version: 0.1.4
+ sha256: 502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c
+ requires_python: '>=3.6'
- conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py313h78bf25f_0.conda
sha256: dc26da204d67948118207322b563a010720497f14dd4b7b0a385bf69a73016ad
md5: 65899d37680aab12f5e33ad07d15d1fd
@@ -423,6 +501,17 @@ packages:
- pkg:pypi/astroid?source=hash-mapping
size: 520275
timestamp: 1762776294541
+- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
+ name: asttokens
+ version: 3.0.1
+ sha256: 15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a
+ requires_dist:
+ - astroid>=2,<5 ; extra == 'astroid'
+ - astroid>=2,<5 ; extra == 'test'
+ - pytest<9.0 ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - pytest-xdist ; extra == 'test'
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
name: astunparse
version: 1.6.3
@@ -520,6 +609,13 @@ packages:
- pytest ; extra == 'development'
- types-colorama ; extra == 'development'
requires_python: '>=3.6'
+- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
+ name: comm
+ version: 0.2.3
+ sha256: c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417
+ requires_dist:
+ - pytest ; extra == 'test'
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
name: contourpy
version: 1.3.3
@@ -608,6 +704,16 @@ packages:
- pytest-cov ; extra == 'tests'
- pytest-xdist ; extra == 'tests'
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
+ name: debugpy
+ version: 1.8.19
+ sha256: 360ffd231a780abbc414ba0f005dad409e71c78637efe8f2bd75837132a41d38
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
+ name: decorator
+ version: 5.2.1
+ sha256: d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a
+ requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
sha256: c0c91bd91e59940091cec1760db51a82a58e9c64edf4b808bd2da94201ccfdb4
md5: eec5b361dbbaa69dba05050977a414b0
@@ -620,6 +726,19 @@ packages:
- pkg:pypi/dill?source=hash-mapping
size: 94889
timestamp: 1764517905571
+- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
+ name: executing
+ version: 2.2.1
+ sha256: 760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017
+ requires_dist:
+ - asttokens>=2.1.0 ; extra == 'tests'
+ - ipython ; extra == 'tests'
+ - pytest ; extra == 'tests'
+ - coverage ; extra == 'tests'
+ - coverage-enable-subprocess ; extra == 'tests'
+ - littleutils ; extra == 'tests'
+ - rich ; python_full_version >= '3.11' and extra == 'tests'
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
name: flatbuffers
version: 25.12.19
@@ -827,6 +946,98 @@ packages:
- pkg:pypi/importlib-metadata?source=hash-mapping
size: 34641
timestamp: 1747934053147
+- pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
+ name: ipykernel
+ version: 7.1.0
+ sha256: 763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c
+ requires_dist:
+ - appnope>=0.1.2 ; sys_platform == 'darwin'
+ - comm>=0.1.1
+ - debugpy>=1.6.5
+ - ipython>=7.23.1
+ - jupyter-client>=8.0.0
+ - jupyter-core>=4.12,!=5.0.*
+ - matplotlib-inline>=0.1
+ - nest-asyncio>=1.4
+ - packaging>=22
+ - psutil>=5.7
+ - pyzmq>=25
+ - tornado>=6.2
+ - traitlets>=5.4.0
+ - coverage[toml] ; extra == 'cov'
+ - matplotlib ; extra == 'cov'
+ - pytest-cov ; extra == 'cov'
+ - trio ; extra == 'cov'
+ - intersphinx-registry ; extra == 'docs'
+ - myst-parser ; extra == 'docs'
+ - pydata-sphinx-theme ; extra == 'docs'
+ - sphinx-autodoc-typehints ; extra == 'docs'
+ - sphinx<8.2.0 ; extra == 'docs'
+ - sphinxcontrib-github-alt ; extra == 'docs'
+ - sphinxcontrib-spelling ; extra == 'docs'
+ - trio ; extra == 'docs'
+ - pyqt5 ; extra == 'pyqt5'
+ - pyside6 ; extra == 'pyside6'
+ - flaky ; extra == 'test'
+ - ipyparallel ; extra == 'test'
+ - pre-commit ; extra == 'test'
+ - pytest-asyncio>=0.23.5 ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - pytest-timeout ; extra == 'test'
+ - pytest>=7.0,<9 ; extra == 'test'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
+ name: ipython
+ version: 9.8.0
+ sha256: ebe6d1d58d7d988fbf23ff8ff6d8e1622cfdb194daf4b7b73b792c4ec3b85385
+ requires_dist:
+ - colorama>=0.4.4 ; sys_platform == 'win32'
+ - decorator>=4.3.2
+ - ipython-pygments-lexers>=1.0.0
+ - jedi>=0.18.1
+ - matplotlib-inline>=0.1.5
+ - pexpect>4.3 ; sys_platform != 'emscripten' and sys_platform != 'win32'
+ - prompt-toolkit>=3.0.41,<3.1.0
+ - pygments>=2.11.0
+ - stack-data>=0.6.0
+ - traitlets>=5.13.0
+ - typing-extensions>=4.6 ; python_full_version < '3.12'
+ - black ; extra == 'black'
+ - docrepr ; extra == 'doc'
+ - exceptiongroup ; extra == 'doc'
+ - intersphinx-registry ; extra == 'doc'
+ - ipykernel ; extra == 'doc'
+ - ipython[matplotlib,test] ; extra == 'doc'
+ - setuptools>=70.0 ; extra == 'doc'
+ - sphinx-toml==0.0.4 ; extra == 'doc'
+ - sphinx-rtd-theme>=0.1.8 ; extra == 'doc'
+ - sphinx>=8.0 ; extra == 'doc'
+ - typing-extensions ; extra == 'doc'
+ - pytest>=7.0.0 ; extra == 'test'
+ - pytest-asyncio>=1.0.0 ; extra == 'test'
+ - testpath>=0.2 ; extra == 'test'
+ - packaging>=20.1.0 ; extra == 'test'
+ - setuptools>=61.2 ; extra == 'test'
+ - ipython[test] ; extra == 'test-extra'
+ - curio ; extra == 'test-extra'
+ - jupyter-ai ; extra == 'test-extra'
+ - ipython[matplotlib] ; extra == 'test-extra'
+ - nbformat ; extra == 'test-extra'
+ - nbclient ; extra == 'test-extra'
+ - ipykernel>6.30 ; extra == 'test-extra'
+ - numpy>=1.27 ; extra == 'test-extra'
+ - pandas>2.1 ; extra == 'test-extra'
+ - trio>=0.1.0 ; extra == 'test-extra'
+ - matplotlib>3.9 ; extra == 'matplotlib'
+ - ipython[doc,matplotlib,test,test-extra] ; extra == 'all'
+ requires_python: '>=3.11'
+- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
+ name: ipython-pygments-lexers
+ version: 1.1.1
+ sha256: a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c
+ requires_dist:
+ - pygments
+ requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
sha256: 13b0005877f553eb2e5c50447c9d0047e7257124ec2d1569d7dad35697790237
md5: 55a61979242077b2cc377c74326ea9f0
@@ -839,11 +1050,98 @@ packages:
- pkg:pypi/isort?source=hash-mapping
size: 74876
timestamp: 1760192714356
+- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
+ name: jedi
+ version: 0.19.2
+ sha256: a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9
+ requires_dist:
+ - parso>=0.8.4,<0.9.0
+ - jinja2==2.11.3 ; extra == 'docs'
+ - markupsafe==1.1.1 ; extra == 'docs'
+ - pygments==2.8.1 ; extra == 'docs'
+ - alabaster==0.7.12 ; extra == 'docs'
+ - babel==2.9.1 ; extra == 'docs'
+ - chardet==4.0.0 ; extra == 'docs'
+ - commonmark==0.8.1 ; extra == 'docs'
+ - docutils==0.17.1 ; extra == 'docs'
+ - future==0.18.2 ; extra == 'docs'
+ - idna==2.10 ; extra == 'docs'
+ - imagesize==1.2.0 ; extra == 'docs'
+ - mock==1.0.1 ; extra == 'docs'
+ - packaging==20.9 ; extra == 'docs'
+ - pyparsing==2.4.7 ; extra == 'docs'
+ - pytz==2021.1 ; extra == 'docs'
+ - readthedocs-sphinx-ext==2.1.4 ; extra == 'docs'
+ - recommonmark==0.5.0 ; extra == 'docs'
+ - requests==2.25.1 ; extra == 'docs'
+ - six==1.15.0 ; extra == 'docs'
+ - snowballstemmer==2.1.0 ; extra == 'docs'
+ - sphinx-rtd-theme==0.4.3 ; extra == 'docs'
+ - sphinx==1.8.5 ; extra == 'docs'
+ - sphinxcontrib-serializinghtml==1.1.4 ; extra == 'docs'
+ - sphinxcontrib-websupport==1.2.4 ; extra == 'docs'
+ - urllib3==1.26.4 ; extra == 'docs'
+ - flake8==5.0.4 ; extra == 'qa'
+ - mypy==0.971 ; extra == 'qa'
+ - types-setuptools==67.2.0.1 ; extra == 'qa'
+ - django ; extra == 'testing'
+ - attrs ; extra == 'testing'
+ - colorama ; extra == 'testing'
+ - docopt ; extra == 'testing'
+ - pytest<9.0.0 ; extra == 'testing'
+ requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
name: joblib
version: 1.5.3
sha256: 5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
+ name: jupyter-client
+ version: 8.7.0
+ sha256: 3671a94fd25e62f5f2f554f5e95389c2294d89822378a5f2dd24353e1494a9e0
+ requires_dist:
+ - jupyter-core>=5.1
+ - python-dateutil>=2.8.2
+ - pyzmq>=25.0
+ - tornado>=6.4.1
+ - traitlets>=5.3
+ - ipykernel ; extra == 'docs'
+ - myst-parser ; extra == 'docs'
+ - pydata-sphinx-theme ; extra == 'docs'
+ - sphinx-autodoc-typehints ; extra == 'docs'
+ - sphinx>=4 ; extra == 'docs'
+ - sphinxcontrib-github-alt ; extra == 'docs'
+ - sphinxcontrib-spelling ; extra == 'docs'
+ - anyio ; extra == 'test'
+ - coverage ; extra == 'test'
+ - ipykernel>=6.14 ; extra == 'test'
+ - mypy ; extra == 'test'
+ - paramiko ; sys_platform == 'win32' and extra == 'test'
+ - pre-commit ; extra == 'test'
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - pytest-jupyter[client]>=0.6.2 ; extra == 'test'
+ - pytest-timeout ; extra == 'test'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
+ name: jupyter-core
+ version: 5.9.1
+ sha256: ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407
+ requires_dist:
+ - platformdirs>=2.5
+ - traitlets>=5.3
+ - intersphinx-registry ; extra == 'docs'
+ - myst-parser ; extra == 'docs'
+ - pydata-sphinx-theme ; extra == 'docs'
+ - sphinx-autodoc-typehints ; extra == 'docs'
+ - sphinxcontrib-spelling ; extra == 'docs'
+ - traitlets ; extra == 'docs'
+ - ipykernel ; extra == 'test'
+ - pre-commit ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - pytest-timeout ; extra == 'test'
+ - pytest<9 ; extra == 'test'
+ requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
name: keras
version: 3.13.0
@@ -1307,6 +1605,18 @@ packages:
- setuptools-scm>=7 ; extra == 'dev'
- setuptools>=64 ; extra == 'dev'
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
+ name: matplotlib-inline
+ version: 0.2.1
+ sha256: d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76
+ requires_dist:
+ - traitlets
+ - flake8 ; extra == 'test'
+ - nbdime ; extra == 'test'
+ - nbval ; extra == 'test'
+ - notebook ; extra == 'test'
+ - pytest ; extra == 'test'
+ requires_python: '>=3.9'
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
sha256: 9b0037171dad0100f0296699a11ae7d355237b55f42f9094aebc0f41512d96a1
md5: 827064ddfe0de2917fb29f1da4f8f533
@@ -1408,6 +1718,11 @@ packages:
purls: []
size: 797030
timestamp: 1738196177597
+- pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
+ name: nest-asyncio
+ version: 1.6.0
+ sha256: 87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c
+ requires_python: '>=3.5'
- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
name: numpy
version: 2.4.0
@@ -1988,6 +2303,17 @@ packages:
- ibis-framework>=9.0.0 ; extra == 'all'
- polars>=0.20.0 ; extra == 'all'
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
+ name: parso
+ version: 0.8.5
+ sha256: 646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887
+ requires_dist:
+ - pytest ; extra == 'testing'
+ - docopt ; extra == 'testing'
+ - flake8==5.0.4 ; extra == 'qa'
+ - mypy==0.971 ; extra == 'qa'
+ - types-setuptools==67.2.0.1 ; extra == 'qa'
+ requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
name: patsy
version: 1.0.2
@@ -1998,6 +2324,12 @@ packages:
- pytest-cov ; extra == 'test'
- scipy ; extra == 'test'
requires_python: '>=3.6'
+- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
+ name: pexpect
+ version: 4.9.0
+ sha256: 7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523
+ requires_dist:
+ - ptyprocess>=0.5
- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
name: pillow
version: 12.0.0
@@ -2109,7 +2441,7 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: 781b8e425980ab36d861eb64e6211b9ccf74fc6759001690d1556f7475f63bd5
+ sha256: ce45a3ae37e590d3d8fabac6921a207f1da8cd4a98382b1dfb25f5f145ede0b3
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -2122,7 +2454,15 @@ packages:
- pandera>=0.27.1,<0.28
- xgboost>=3.1.2,<4
- optuna>=4.6.0,<5
+ - ipykernel>=7.1.0,<8
requires_python: '>=3.11,<3.14'
+- pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
+ name: prompt-toolkit
+ version: 3.0.52
+ sha256: 9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955
+ requires_dist:
+ - wcwidth
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
version: 6.33.2
@@ -2138,6 +2478,118 @@ packages:
version: 6.33.2
sha256: d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/10/a1/c75feb480f60cd768fb6ed00ac362a16a33e5076ec8475a22d8162fb2659/psutil-7.2.0-cp36-abi3-macosx_11_0_arm64.whl
+ name: psutil
+ version: 7.2.0
+ sha256: 24151011c21fadd94214d7139d7c6c54569290d7e553989bdf0eab73b13beb8c
+ requires_dist:
+ - pytest ; extra == 'dev'
+ - pytest-instafail ; extra == 'dev'
+ - pytest-xdist ; extra == 'dev'
+ - setuptools ; extra == 'dev'
+ - abi3audit ; extra == 'dev'
+ - black ; extra == 'dev'
+ - check-manifest ; extra == 'dev'
+ - coverage ; extra == 'dev'
+ - packaging ; extra == 'dev'
+ - pylint ; extra == 'dev'
+ - pyperf ; extra == 'dev'
+ - pypinfo ; extra == 'dev'
+ - pytest-cov ; extra == 'dev'
+ - requests ; extra == 'dev'
+ - rstcheck ; extra == 'dev'
+ - ruff ; extra == 'dev'
+ - sphinx ; extra == 'dev'
+ - sphinx-rtd-theme ; extra == 'dev'
+ - toml-sort ; extra == 'dev'
+ - twine ; extra == 'dev'
+ - validate-pyproject[all] ; extra == 'dev'
+ - virtualenv ; extra == 'dev'
+ - vulture ; extra == 'dev'
+ - wheel ; extra == 'dev'
+ - pytest ; extra == 'test'
+ - pytest-instafail ; extra == 'test'
+ - pytest-xdist ; extra == 'test'
+ - setuptools ; extra == 'test'
+ requires_python: '>=3.6'
+- pypi: https://files.pythonhosted.org/packages/12/ff/e93136587c00a543f4bc768b157fac2c47cd77b180d4f4e5c6efb6ea53a2/psutil-7.2.0-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl
+ name: psutil
+ version: 7.2.0
+ sha256: 91f211ba9279e7c61d9d8f84b713cfc38fa161cb0597d5cb3f1ca742f6848254
+ requires_dist:
+ - pytest ; extra == 'dev'
+ - pytest-instafail ; extra == 'dev'
+ - pytest-xdist ; extra == 'dev'
+ - setuptools ; extra == 'dev'
+ - abi3audit ; extra == 'dev'
+ - black ; extra == 'dev'
+ - check-manifest ; extra == 'dev'
+ - coverage ; extra == 'dev'
+ - packaging ; extra == 'dev'
+ - pylint ; extra == 'dev'
+ - pyperf ; extra == 'dev'
+ - pypinfo ; extra == 'dev'
+ - pytest-cov ; extra == 'dev'
+ - requests ; extra == 'dev'
+ - rstcheck ; extra == 'dev'
+ - ruff ; extra == 'dev'
+ - sphinx ; extra == 'dev'
+ - sphinx-rtd-theme ; extra == 'dev'
+ - toml-sort ; extra == 'dev'
+ - twine ; extra == 'dev'
+ - validate-pyproject[all] ; extra == 'dev'
+ - virtualenv ; extra == 'dev'
+ - vulture ; extra == 'dev'
+ - wheel ; extra == 'dev'
+ - pytest ; extra == 'test'
+ - pytest-instafail ; extra == 'test'
+ - pytest-xdist ; extra == 'test'
+ - setuptools ; extra == 'test'
+ requires_python: '>=3.6'
+- pypi: https://files.pythonhosted.org/packages/b8/dd/4c2de9c3827c892599d277a69d2224136800870a8a88a80981de905de28d/psutil-7.2.0-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: psutil
+ version: 7.2.0
+ sha256: f37415188b7ea98faf90fed51131181646c59098b077550246e2e092e127418b
+ requires_dist:
+ - pytest ; extra == 'dev'
+ - pytest-instafail ; extra == 'dev'
+ - pytest-xdist ; extra == 'dev'
+ - setuptools ; extra == 'dev'
+ - abi3audit ; extra == 'dev'
+ - black ; extra == 'dev'
+ - check-manifest ; extra == 'dev'
+ - coverage ; extra == 'dev'
+ - packaging ; extra == 'dev'
+ - pylint ; extra == 'dev'
+ - pyperf ; extra == 'dev'
+ - pypinfo ; extra == 'dev'
+ - pytest-cov ; extra == 'dev'
+ - requests ; extra == 'dev'
+ - rstcheck ; extra == 'dev'
+ - ruff ; extra == 'dev'
+ - sphinx ; extra == 'dev'
+ - sphinx-rtd-theme ; extra == 'dev'
+ - toml-sort ; extra == 'dev'
+ - twine ; extra == 'dev'
+ - validate-pyproject[all] ; extra == 'dev'
+ - virtualenv ; extra == 'dev'
+ - vulture ; extra == 'dev'
+ - wheel ; extra == 'dev'
+ - pytest ; extra == 'test'
+ - pytest-instafail ; extra == 'test'
+ - pytest-xdist ; extra == 'test'
+ - setuptools ; extra == 'test'
+ requires_python: '>=3.6'
+- pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
+ name: ptyprocess
+ version: 0.7.0
+ sha256: 4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35
+- pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
+ name: pure-eval
+ version: 0.2.3
+ sha256: 1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0
+ requires_dist:
+ - pytest ; extra == 'tests'
- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
name: pydantic
version: 2.12.5
@@ -2320,6 +2772,27 @@ packages:
version: 6.0.3
sha256: 2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1
requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
+ name: pyzmq
+ version: 27.1.0
+ sha256: 452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc
+ requires_dist:
+ - cffi ; implementation_name == 'pypy'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
+ name: pyzmq
+ version: 27.1.0
+ sha256: 43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31
+ requires_dist:
+ - cffi ; implementation_name == 'pypy'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ name: pyzmq
+ version: 27.1.0
+ sha256: 3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233
+ requires_dist:
+ - cffi ; implementation_name == 'pypy'
+ requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002
md5: d7d95fc8287ea7bf33e0e7116d2b95ec
@@ -2864,6 +3337,19 @@ packages:
- typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
- sqlcipher3-binary ; extra == 'sqlcipher'
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
+ name: stack-data
+ version: 0.6.3
+ sha256: d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695
+ requires_dist:
+ - executing>=1.2.0
+ - asttokens>=2.1.0
+ - pure-eval
+ - pytest ; extra == 'tests'
+ - typeguard ; extra == 'tests'
+ - pygments ; extra == 'tests'
+ - littleutils ; extra == 'tests'
+ - cython ; extra == 'tests'
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: statsmodels
version: 0.14.6
@@ -3184,6 +3670,21 @@ packages:
- pkg:pypi/tomlkit?source=hash-mapping
size: 38777
timestamp: 1749127286558
+- pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ name: tornado
+ version: 6.5.4
+ sha256: e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
+ name: tornado
+ version: 6.5.4
+ sha256: d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ name: tornado
+ version: 6.5.4
+ sha256: d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
name: tqdm
version: 4.67.1
@@ -3200,6 +3701,21 @@ packages:
- requests ; extra == 'telegram'
- ipywidgets>=6 ; extra == 'notebook'
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
+ name: traitlets
+ version: 5.14.3
+ sha256: b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f
+ requires_dist:
+ - myst-parser ; extra == 'docs'
+ - pydata-sphinx-theme ; extra == 'docs'
+ - sphinx ; extra == 'docs'
+ - argcomplete>=3.0.3 ; extra == 'test'
+ - mypy>=1.7.0 ; extra == 'test'
+ - pre-commit ; extra == 'test'
+ - pytest-mock ; extra == 'test'
+ - pytest-mypy-testing ; extra == 'test'
+ - pytest>=7.0,<8.2 ; extra == 'test'
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
name: typeguard
version: 4.4.4
@@ -3261,6 +3777,11 @@ packages:
- pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks'
- backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
+ name: wcwidth
+ version: 0.2.14
+ sha256: a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1
+ requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
name: werkzeug
version: 3.1.4
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index e74cf55..c99d49b 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -22,27 +22,20 @@ def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.Da
"""Preprocess ratios DataFrame by excluding chromosomes, adding region column and transposing.
returns a x by 1 dataframe with regions as columns.
"""
-
+ # sanitize columns
+ ratios_df = ratios_df[["chr", "start", "end", "ratio"]].copy()
# santize chr column
ratios_df["chr"] = ratios_df["chr"].astype(str).str.replace("chr", "", regex=False)
# exclude chromosomes
- masked_ratios = ratios_df[~ratios_df["chr"].isin(exclude_chrs)].copy()
+ ratios_df = ratios_df[~ratios_df["chr"].isin(exclude_chrs)].copy()
# add region column
- masked_ratios["region"] = (
- masked_ratios["chr"]
- + ":"
- + masked_ratios["start"].astype(str)
- + "-"
- + masked_ratios["end"].astype(str)
- )
+ ratios_df["region"] = (ratios_df["chr"] + ":" + ratios_df["start"].astype(str) + "-" + ratios_df["end"].astype(str)) # type: ignore
# drop chr, start, end columns
- masked_ratios = masked_ratios.drop(columns=["chr", "start", "end"])
- # set region as index
- masked_ratios = masked_ratios.set_index("region")
- # transpose to have regions as columns
- masked_ratios = masked_ratios.T
+ ratios_df.drop(columns=["chr", "start", "end"], inplace=True)
+ # set region as index and transpose
+ ratios_df = ratios_df.set_index("region").T
- return masked_ratios
+ return ratios_df
def build_ensemble(n_feat: int, pca: PCA, models: list[Model]) -> Model:
diff --git a/src/preface/lib/schemas.py b/src/preface/lib/schemas.py
deleted file mode 100644
index 2b5520d..0000000
--- a/src/preface/lib/schemas.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import pandera.pandas as pa
-
-
-class SampleSchema(pa.DataFrameSchema):
- """
- Sample schema for samplesheet entries.
- """
-
- ff = pa.Column(float, checks=[pa.Check.ge(0.0), pa.Check.le(1.0)], nullable=True)
- filepath = pa.Column(str, checks=[pa.Check.str_matches(r".+\.bed$")])
- id = pa.Column(str)
- sex = pa.Column(str, checks=pa.Check.isin(["M", "F"]))
-
-
-class SampleDataSchema(pa.DataFrameSchema):
- """
- Sample data model for samplesheet entries with optional fetal fraction.
- """
-
- chr = pa.Column(
- str, checks=pa.Check.str_matches(r"^(chr)?([1-9]|1[0-9]|2[0-2]|X|Y|MT)$")
- )
- start = pa.Column(int, checks=pa.Check.ge(0), coerce=True)
- end = pa.Column(int, checks=pa.Check.ge(0), coerce=True)
- ratio = pa.Column(float, checks=[pa.Check.ge(0.0), pa.Check.le(1.0)], nullable=True)
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 2f7734c..9317501 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -1,5 +1,4 @@
from pathlib import Path
-
import numpy as np
import numpy.typing as npt
import optuna
diff --git a/src/preface/predict.py b/src/preface/predict.py
index 7ce4711..d5d4aa4 100644
--- a/src/preface/predict.py
+++ b/src/preface/predict.py
@@ -4,9 +4,9 @@
import pandas as pd
import typer
-from tensorflow.keras import load_model # pylint: disable=no-name-in-module,import-error # type: ignore
-from preface.lib.schemas import SampleDataSchema
+from tensorflow.keras.saving import load_model # pylint: disable=no-name-in-module,import-error # type: ignore
from preface.lib.functions import preprocess_ratios
+from rich import print
def preface_predict(
@@ -21,13 +21,6 @@ def preface_predict(
preface_model = load_model(model_path)
ratios = pd.read_csv(infile, sep="\t")
- # Validate input data
- try:
- SampleDataSchema().validate(ratios)
- except Exception as e:
- typer.echo(f"Validation error: {e}")
- raise
-
# Preprocess ratios
preprocessed_ratios = preprocess_ratios(ratios, exclude_chrs=[])
@@ -39,8 +32,8 @@ def preface_predict(
# x_ratio = float(np.nan)
ff_pred, sex_pred = preface_model.predict(preprocessed_ratios.values)
- typer.echo(f"FF = {ff_pred:.4g}%")
- typer.echo(f"Sex = {sex_pred}")
+ print(f"FF = {ff_pred:.4g}%")
+ print(f"Sex = {sex_pred}")
# ffx: float = (x_ratio - intercept_x) / slope_x
@@ -60,11 +53,7 @@ def preface_predict(
# projected_ratio = pca.transform(features_array)[:, :n_feat]
- # prediction: float
- # if is_olm:
- # prediction = float(model.predict(projected_ratio)[0])
- # else:
- # prediction = float(model.predict(projected_ratio).flatten()[0])
+ # prediction = float(model.predict(projected_ratio).flatten()[0])
# prediction = the_intercept + the_slope * prediction
@@ -75,7 +64,7 @@ def preface_predict(
# with open(json_output, "w", encoding="utf-8") as f:
# json.dump(json_dict, f)
# else:
- # typer.echo(json.dumps(json_dict))
+ # print(json.dumps(json_dict))
# else:
- # typer.echo(f"FFX = {ffx:.4g}%")
- # typer.echo(f"PREFACE = {prediction:.4g}%")
+ # print(f"FFX = {ffx:.4g}%")
+ # print(f"PREFACE = {prediction:.4g}%")
diff --git a/src/preface/preface.py b/src/preface/preface.py
index 03fb17a..60b5d43 100644
--- a/src/preface/preface.py
+++ b/src/preface/preface.py
@@ -2,13 +2,32 @@
PREFACE CLI entry point.
"""
-import typer
+import os
+import warnings
+import logging
+from rich.logging import RichHandler
-from preface import __version__
-from preface.predict import preface_predict
-from preface.train import preface_train
-from preface.utils.ffy import wisecondorx_ffy
-from preface.utils.npz_to_parquet import npz_to_parquet
+# Suppress warnings
+os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
+warnings.filterwarnings("ignore", category=FutureWarning, module="keras")
+warnings.filterwarnings("ignore", category=FutureWarning, module="tensorflow")
+warnings.filterwarnings("ignore", category=UserWarning, module="sklearn")
+
+import typer # noqa: E402
+
+from preface import __version__ # noqa: E402
+from preface.predict import preface_predict # noqa: E402
+from preface.train import preface_train # noqa: E402
+from preface.utils.ffy import wisecondorx_ffy # noqa: E402
+from preface.utils.npz_to_parquet import npz_to_parquet # noqa: E402
+
+# Configure logging
+logging.basicConfig(
+ level="NOTSET",
+ format="%(message)s",
+ datefmt="[%X]",
+ handlers=[RichHandler(rich_tracebacks=True, tracebacks_suppress=[typer])],
+)
# Version
VERSION: str = __version__
@@ -17,7 +36,7 @@
app = typer.Typer(help="PREFACE - PREdict FetAl ComponEnt")
app.command(name="predict")(preface_predict)
app.command(name="train")(preface_train)
-app.command(name="version")(lambda: typer.echo(f"PREFACE version {VERSION}"))
+app.command(name="version")(lambda: print(f"PREFACE version {VERSION}"))
# Utilities group
utils_app = typer.Typer(help="Utility scripts")
diff --git a/src/preface/train.py b/src/preface/train.py
index 441821b..50fc33d 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -5,11 +5,11 @@
import os
import time
from pathlib import Path
+import logging
from enum import Enum
import pandas as pd
import typer
-from pandera.errors import SchemaError
import sklearn
from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
from sklearn.impute import IterativeImputer
@@ -26,7 +26,6 @@
)
from preface.lib.xgboost import xgboost_tune, xgboost_fit
from preface.lib.neural import neural_tune, neural_fit
-from preface.lib.schemas import SampleDataSchema, SampleSchema
# Constants
EXCLUDE_CHRS: list[str] = ["13", "18", "21", "X", "Y"]
@@ -78,41 +77,30 @@ def preface_train(
# Load samplesheet
samplesheet_data: pd.DataFrame = pd.read_csv(
- samplesheet, comment="#", dtype={"sex": str, "ID": str}, index_col="ID"
+ samplesheet, comment="#", sep="\t", dtype={"sex": str, "ID": str}
)
- # Validate samplesheet
- samplesheet_schema = SampleSchema()
- try:
- samplesheet_schema.validate(samplesheet_data)
- except SchemaError as e:
- typer.echo(f"Error validating samplesheet: {e}")
- raise typer.Exit(code=1)
-
# Check samples
if len(samplesheet_data) < n_feat:
- typer.echo(f"Please provide at least {n_feat} labeled samples.")
+ logging.error(f"Please provide at least {n_feat} labeled samples.")
raise typer.Exit(code=1)
# Load all sample data
- typer.echo("Loading samples...")
-
+ logging.info("Loading samples...")
# instantiate lists for ratios
ratios_list: list[pd.DataFrame] = []
- # instantiate schema
- sample_data_schema = SampleDataSchema()
-
# instantiate number of bins checker
number_of_bins: int = -1
# parse data
- for _, sample in samplesheet_data.iterrows():
+ for i, sample in samplesheet_data.iterrows():
+ logging.info(f"Processing sample {sample['ID']} ({i + 1}/{len(samplesheet_data)})...") # type: ignore
if (
not Path(sample["filepath"]).exists()
- or not Path(sample["filepath"]).is_file()
+ or not Path(sample["filepath"]).is_file() # noqa: W503
):
- typer.echo(f"Error: File '{sample['filepath']}' does not exist.")
+ logging.error(f"File '{sample['filepath']}' does not exist.")
raise typer.Exit(code=1)
# load ratios (bed format)
ratios = pd.read_csv(
@@ -121,21 +109,13 @@ def preface_train(
sep="\t",
header=0,
)
- # validate ratios
- try:
- sample_data_schema.validate(ratios)
- except SchemaError as e:
- typer.echo(
- f"Error validating sample data for file {sample['filepath']}: {e}"
- )
- raise typer.Exit(code=1)
# check number of bins consistency
number_of_bins_current = len(ratios)
if number_of_bins == -1:
number_of_bins = number_of_bins_current
elif number_of_bins != number_of_bins_current:
- typer.echo("Error: Input BED files have different numbers of bins.")
+ logging.error("Input BED files have different numbers of bins.")
raise typer.Exit(code=1)
# preprocess ratios
@@ -143,20 +123,20 @@ def preface_train(
# add sample metadata columns to transposed ratios
masked_ratios["id"] = sample["ID"]
- masked_ratios["sex"] = sample["sex"]
+ masked_ratios["sex"] = sample["sex"].map({"M": 1, "F": 0})
masked_ratios["ff"] = sample["FF"]
# add to list
ratios_list.append(masked_ratios)
# Stack dataframes horizontally
- typer.echo("Merging sample data...")
+ logging.info("Merging sample data...")
ratios_per_sample: pd.DataFrame = pd.concat(ratios_list, axis=0)
# set index to ID column
ratios_per_sample = ratios_per_sample.set_index("id")
- typer.echo("Creating training frame...")
+ logging.info("Creating training frame...")
# Handle NaN values
# Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
@@ -168,14 +148,13 @@ def preface_train(
# Check sklearn version for compatibility
sk_version = sklearn.__version__
if sk_version != "1.8.0":
- typer.echo(f"""Warning: PREFACE uses imputation and was developed using scikit-learn version 1.8.0.
+ logging.warning(f"""PREFACE uses imputation and was developed using scikit-learn version 1.8.0.
Since imputation is still experimental, it may be subject to change in other versions.
You are using version {sk_version}. Proceed with caution.""")
- typer.echo("Imputing missing values using MICE...")
-
+ logging.info("Imputing missing values using MICE... This might take a while.")
imputer = IterativeImputer(
- random_state=42, max_iter=10, initial_strategy="mean"
+ random_state=42, max_iter=10, initial_strategy="mean", verbose=1
)
training_df_array = imputer.fit_transform(ratios_per_sample)
ratios_per_sample = pd.DataFrame(
@@ -185,7 +164,7 @@ def preface_train(
)
# Option 2: Assume missing values are zero (no change)
else:
- typer.echo("Assuming missing values are zero...")
+ logging.info("Assuming missing values are zero...")
ratios_per_sample = ratios_per_sample.fillna(0.0)
# Split into features and labels
@@ -194,7 +173,7 @@ def preface_train(
# labels for regression (fetal fraction)
y_ff_all = y_all["ff"]
# labels for classification (sex)
- y_sex_all = y_all["sex"].map({"M": 1, "F": 0})
+ y_sex_all = y_all["sex"]
# Reduce dimensionality with PCA
global_pca = PCA(n_components=n_feat)
@@ -203,7 +182,7 @@ def preface_train(
params = {}
if tune:
# Enable hyperparameter tuning
- typer.echo("Tuning hyperparameters...")
+ logging.info("Tuning hyperparameters...")
if model == ModelOptions.NEURAL:
params = neural_tune(x_all_pca, y_all.to_numpy(), out_dir)
elif model == ModelOptions.XGBOOST:
@@ -218,7 +197,7 @@ def preface_train(
# Set up k-fold cross-validation
kf: KFold = KFold(n_splits=n_folds, shuffle=True, random_state=42)
for fold, (train_idx, test_idx) in enumerate(kf.split(x_all_pca), 1):
- typer.echo(f"Processing Fold {fold}/{n_folds}...")
+ logging.info(f"Processing Fold {fold}/{n_folds}...")
# split into train and test sets
x_train, x_test = x_all_pca[train_idx], x_all_pca[test_idx]
@@ -227,7 +206,7 @@ def preface_train(
y_train_class, y_test_class = y_sex_all[train_idx], y_sex_all[test_idx]
# Train
- typer.echo(f"Training fold {fold}...")
+ logging.info(f"Training fold {fold}...")
if model == ModelOptions.NEURAL:
model, predictions = neural_fit(
x_train,
@@ -284,12 +263,12 @@ def preface_train(
fold_metrics_df.to_csv(out_dir / "training_fold_metrics.csv", index=False)
# Build ensemble model from fold models
- typer.echo("Building ensemble model from fold models...")
+ logging.info("Building ensemble model from fold models...")
ensemble_model = build_ensemble(len(x_all.columns), global_pca, fold_models)
ensemble_model.save(out_dir / "PREFACE")
# Final evaluation on all training data
- typer.echo("Evaluating final model on all training data...")
+ logging.info("Evaluating final model on all training data...")
predictions = ensemble_model.predict(x_all)
info_overall = plot_regression_performance(
predictions[0].flatten(),
@@ -310,7 +289,7 @@ def preface_train(
"""
)
- typer.echo(
+ logging.info(
f"Finished! Consult '{out_dir / 'training_statistics.txt'}' "
"to analyse your model's performance."
)
diff --git a/src/preface/utils/npz_to_parquet.py b/src/preface/utils/npz_to_parquet.py
index 2b2d26d..4f61607 100644
--- a/src/preface/utils/npz_to_parquet.py
+++ b/src/preface/utils/npz_to_parquet.py
@@ -2,8 +2,7 @@
Convert NPZ to Parquet utility.
"""
-# pylint: disable=broad-exception-caught
-
+import logging
import os
from typing import List
@@ -19,12 +18,12 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
try:
npz_data = np.load(npz_path, allow_pickle=True)
except Exception as e:
- typer.echo(f"Error loading {npz_path}: {e}", err=True)
+ logging.error(f"Error loading {npz_path}: {e}")
return
base_name = os.path.splitext(os.path.basename(npz_path))[0]
- typer.echo(f"Processing NPZ file: {npz_path}")
+ logging.info(f"Processing NPZ file: {npz_path}")
for key in npz_data.files:
array = npz_data[key]
@@ -33,7 +32,7 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
output_filename = f"{base_name}_{key}.parquet"
output_filepath = os.path.join(output_dir, output_filename)
- typer.echo(
+ logging.info(
f" Converting array '{key}' (shape: {array.shape}, "
f"dtype: {array.dtype}) to {output_filepath}"
)
@@ -53,10 +52,9 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
array, columns=[f"{key}_{i}" for i in range(array.shape[1])]
)
elif array.ndim > 2:
- typer.echo(
+ logging.warning(
f" Warning: Array '{key}' has {array.ndim} dimensions. "
- "Flattening for Parquet storage.",
- err=True,
+ "Flattening for Parquet storage."
)
# Flatten to 1D and then treat as a single-column DataFrame
df = pd.DataFrame({key: array.flatten()})
@@ -65,9 +63,9 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
try:
df.to_parquet(output_filepath, index=False)
- typer.echo(f" Successfully saved '{key}' to {output_filepath}")
+ logging.info(f" Successfully saved '{key}' to {output_filepath}")
except Exception as e:
- typer.echo(f" Error saving array '{key}' to Parquet: {e}", err=True)
+ logging.error(f" Error saving array '{key}' to Parquet: {e}")
def npz_to_parquet(
@@ -85,7 +83,7 @@ def npz_to_parquet(
for npz_file in npz_files:
if not os.path.exists(npz_file):
- typer.echo(f"Error: Input file not found: {npz_file}", err=True)
+ logging.error(f"Error: Input file not found: {npz_file}")
continue
_convert_single_npz(npz_file, output_dir)
From 3251492cd306015f148ea824f5b322881a773547 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sat, 27 Dec 2025 19:18:44 +0100
Subject: [PATCH 12/50] add Docker build infrastructure
---
.dockerignore | 13 +++++++++++++
Dockerfile | 4 ++--
Makefile | 12 ++++++++++++
3 files changed, 27 insertions(+), 2 deletions(-)
create mode 100644 .dockerignore
create mode 100644 Makefile
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..ca28682
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,13 @@
+.git
+.pixi
+.ruff_cache
+.vscode
+__pycache__
+*.pyc
+*.pyo
+*.pyd
+.DS_Store
+data
+examples
+.gemini
+pixi.lock
diff --git a/Dockerfile b/Dockerfile
index 7d927df..dd50fe6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,6 +4,6 @@ WORKDIR /app
COPY . /app
-RUN pip install .
+RUN pip install --no-cache-dir .
-ENTRYPOINT ["PREFACE"]
+ENTRYPOINT ["PREFACE"]
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a88979c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+IMAGE_NAME ?= preface
+REGISTRY ?= quay.io
+USERNAME ?= matthdsm
+TAG ?= latest
+
+.PHONY: build push
+
+build:
+ docker build -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) .
+
+push:
+ docker push $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG)
From 31ed2890e93d68f651d3889dfaae7d602155bbe4 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sat, 27 Dec 2025 19:22:08 +0100
Subject: [PATCH 13/50] use package version as default docker tag
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index a88979c..e6e6e86 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
IMAGE_NAME ?= preface
REGISTRY ?= quay.io
USERNAME ?= matthdsm
-TAG ?= latest
+TAG ?= $(shell sed -n 's/^__version__ = "\(.*\)"/\1/p' src/preface/__init__.py)
.PHONY: build push
From 1241c27f60be7386af1207f4f1213abca6342092 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sat, 27 Dec 2025 19:31:02 +0100
Subject: [PATCH 14/50] add bump-version make target
---
Makefile | 8 +-
pixi.lock | 670 +------------------------------------------------
pyproject.toml | 3 +-
3 files changed, 10 insertions(+), 671 deletions(-)
diff --git a/Makefile b/Makefile
index e6e6e86..34cfe8a 100644
--- a/Makefile
+++ b/Makefile
@@ -3,10 +3,16 @@ REGISTRY ?= quay.io
USERNAME ?= matthdsm
TAG ?= $(shell sed -n 's/^__version__ = "\(.*\)"/\1/p' src/preface/__init__.py)
-.PHONY: build push
+.PHONY: build push bump-version
build:
docker build -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) .
push:
docker push $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG)
+
+bump-version:
+ @if [ -z "$(v)" ]; then echo "Usage: make bump-version v=1.0.0"; exit 1; fi
+ python3 -c "import re; content = open('src/preface/__init__.py').read(); open('src/preface/__init__.py', 'w').write(re.sub(r'__version__ = \".*\"', '__version__ = \"$(v)\"', content))"
+ @echo "Version bumped to $(v)"
+
diff --git a/pixi.lock b/pixi.lock
index 414b141..31316ca 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -44,19 +44,13 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
@@ -65,13 +59,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
@@ -80,12 +68,9 @@ environments:
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
@@ -93,24 +78,14 @@ environments:
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/12/ff/e93136587c00a543f4bc768b157fac2c47cd77b180d4f4e5c6efb6ea53a2/psutil-7.2.0-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -119,24 +94,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
@@ -177,19 +145,13 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
@@ -198,13 +160,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
@@ -213,36 +169,23 @@ environments:
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/b8/dd/4c2de9c3827c892599d277a69d2224136800870a8a88a80981de905de28d/psutil-7.2.0-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
@@ -251,24 +194,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
@@ -303,20 +239,13 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
@@ -324,13 +253,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
@@ -339,36 +262,23 @@ environments:
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/10/a1/c75feb480f60cd768fb6ed00ac362a16a33e5076ec8475a22d8162fb2659/psutil-7.2.0-cp36-abi3-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
@@ -377,24 +287,17 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
@@ -451,18 +354,6 @@ packages:
- tomli ; python_full_version < '3.11'
- tzdata ; extra == 'tz'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- name: annotated-types
- version: 0.7.0
- sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53
- requires_dist:
- - typing-extensions>=4.0.0 ; python_full_version < '3.9'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl
- name: appnope
- version: 0.1.4
- sha256: 502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c
- requires_python: '>=3.6'
- conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py313h78bf25f_0.conda
sha256: dc26da204d67948118207322b563a010720497f14dd4b7b0a385bf69a73016ad
md5: 65899d37680aab12f5e33ad07d15d1fd
@@ -501,17 +392,6 @@ packages:
- pkg:pypi/astroid?source=hash-mapping
size: 520275
timestamp: 1762776294541
-- pypi: https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl
- name: asttokens
- version: 3.0.1
- sha256: 15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a
- requires_dist:
- - astroid>=2,<5 ; extra == 'astroid'
- - astroid>=2,<5 ; extra == 'test'
- - pytest<9.0 ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - pytest-xdist ; extra == 'test'
- requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
name: astunparse
version: 1.6.3
@@ -609,13 +489,6 @@ packages:
- pytest ; extra == 'development'
- types-colorama ; extra == 'development'
requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl
- name: comm
- version: 0.2.3
- sha256: c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417
- requires_dist:
- - pytest ; extra == 'test'
- requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
name: contourpy
version: 1.3.3
@@ -704,16 +577,6 @@ packages:
- pytest-cov ; extra == 'tests'
- pytest-xdist ; extra == 'tests'
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl
- name: debugpy
- version: 1.8.19
- sha256: 360ffd231a780abbc414ba0f005dad409e71c78637efe8f2bd75837132a41d38
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl
- name: decorator
- version: 5.2.1
- sha256: d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a
- requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
sha256: c0c91bd91e59940091cec1760db51a82a58e9c64edf4b808bd2da94201ccfdb4
md5: eec5b361dbbaa69dba05050977a414b0
@@ -726,19 +589,6 @@ packages:
- pkg:pypi/dill?source=hash-mapping
size: 94889
timestamp: 1764517905571
-- pypi: https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl
- name: executing
- version: 2.2.1
- sha256: 760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017
- requires_dist:
- - asttokens>=2.1.0 ; extra == 'tests'
- - ipython ; extra == 'tests'
- - pytest ; extra == 'tests'
- - coverage ; extra == 'tests'
- - coverage-enable-subprocess ; extra == 'tests'
- - littleutils ; extra == 'tests'
- - rich ; python_full_version >= '3.11' and extra == 'tests'
- requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
name: flatbuffers
version: 25.12.19
@@ -946,98 +796,6 @@ packages:
- pkg:pypi/importlib-metadata?source=hash-mapping
size: 34641
timestamp: 1747934053147
-- pypi: https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl
- name: ipykernel
- version: 7.1.0
- sha256: 763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c
- requires_dist:
- - appnope>=0.1.2 ; sys_platform == 'darwin'
- - comm>=0.1.1
- - debugpy>=1.6.5
- - ipython>=7.23.1
- - jupyter-client>=8.0.0
- - jupyter-core>=4.12,!=5.0.*
- - matplotlib-inline>=0.1
- - nest-asyncio>=1.4
- - packaging>=22
- - psutil>=5.7
- - pyzmq>=25
- - tornado>=6.2
- - traitlets>=5.4.0
- - coverage[toml] ; extra == 'cov'
- - matplotlib ; extra == 'cov'
- - pytest-cov ; extra == 'cov'
- - trio ; extra == 'cov'
- - intersphinx-registry ; extra == 'docs'
- - myst-parser ; extra == 'docs'
- - pydata-sphinx-theme ; extra == 'docs'
- - sphinx-autodoc-typehints ; extra == 'docs'
- - sphinx<8.2.0 ; extra == 'docs'
- - sphinxcontrib-github-alt ; extra == 'docs'
- - sphinxcontrib-spelling ; extra == 'docs'
- - trio ; extra == 'docs'
- - pyqt5 ; extra == 'pyqt5'
- - pyside6 ; extra == 'pyside6'
- - flaky ; extra == 'test'
- - ipyparallel ; extra == 'test'
- - pre-commit ; extra == 'test'
- - pytest-asyncio>=0.23.5 ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - pytest-timeout ; extra == 'test'
- - pytest>=7.0,<9 ; extra == 'test'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/f1/df/8ee1c5dd1e3308b5d5b2f2dfea323bb2f3827da8d654abb6642051199049/ipython-9.8.0-py3-none-any.whl
- name: ipython
- version: 9.8.0
- sha256: ebe6d1d58d7d988fbf23ff8ff6d8e1622cfdb194daf4b7b73b792c4ec3b85385
- requires_dist:
- - colorama>=0.4.4 ; sys_platform == 'win32'
- - decorator>=4.3.2
- - ipython-pygments-lexers>=1.0.0
- - jedi>=0.18.1
- - matplotlib-inline>=0.1.5
- - pexpect>4.3 ; sys_platform != 'emscripten' and sys_platform != 'win32'
- - prompt-toolkit>=3.0.41,<3.1.0
- - pygments>=2.11.0
- - stack-data>=0.6.0
- - traitlets>=5.13.0
- - typing-extensions>=4.6 ; python_full_version < '3.12'
- - black ; extra == 'black'
- - docrepr ; extra == 'doc'
- - exceptiongroup ; extra == 'doc'
- - intersphinx-registry ; extra == 'doc'
- - ipykernel ; extra == 'doc'
- - ipython[matplotlib,test] ; extra == 'doc'
- - setuptools>=70.0 ; extra == 'doc'
- - sphinx-toml==0.0.4 ; extra == 'doc'
- - sphinx-rtd-theme>=0.1.8 ; extra == 'doc'
- - sphinx>=8.0 ; extra == 'doc'
- - typing-extensions ; extra == 'doc'
- - pytest>=7.0.0 ; extra == 'test'
- - pytest-asyncio>=1.0.0 ; extra == 'test'
- - testpath>=0.2 ; extra == 'test'
- - packaging>=20.1.0 ; extra == 'test'
- - setuptools>=61.2 ; extra == 'test'
- - ipython[test] ; extra == 'test-extra'
- - curio ; extra == 'test-extra'
- - jupyter-ai ; extra == 'test-extra'
- - ipython[matplotlib] ; extra == 'test-extra'
- - nbformat ; extra == 'test-extra'
- - nbclient ; extra == 'test-extra'
- - ipykernel>6.30 ; extra == 'test-extra'
- - numpy>=1.27 ; extra == 'test-extra'
- - pandas>2.1 ; extra == 'test-extra'
- - trio>=0.1.0 ; extra == 'test-extra'
- - matplotlib>3.9 ; extra == 'matplotlib'
- - ipython[doc,matplotlib,test,test-extra] ; extra == 'all'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl
- name: ipython-pygments-lexers
- version: 1.1.1
- sha256: a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c
- requires_dist:
- - pygments
- requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
sha256: 13b0005877f553eb2e5c50447c9d0047e7257124ec2d1569d7dad35697790237
md5: 55a61979242077b2cc377c74326ea9f0
@@ -1050,98 +808,11 @@ packages:
- pkg:pypi/isort?source=hash-mapping
size: 74876
timestamp: 1760192714356
-- pypi: https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl
- name: jedi
- version: 0.19.2
- sha256: a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9
- requires_dist:
- - parso>=0.8.4,<0.9.0
- - jinja2==2.11.3 ; extra == 'docs'
- - markupsafe==1.1.1 ; extra == 'docs'
- - pygments==2.8.1 ; extra == 'docs'
- - alabaster==0.7.12 ; extra == 'docs'
- - babel==2.9.1 ; extra == 'docs'
- - chardet==4.0.0 ; extra == 'docs'
- - commonmark==0.8.1 ; extra == 'docs'
- - docutils==0.17.1 ; extra == 'docs'
- - future==0.18.2 ; extra == 'docs'
- - idna==2.10 ; extra == 'docs'
- - imagesize==1.2.0 ; extra == 'docs'
- - mock==1.0.1 ; extra == 'docs'
- - packaging==20.9 ; extra == 'docs'
- - pyparsing==2.4.7 ; extra == 'docs'
- - pytz==2021.1 ; extra == 'docs'
- - readthedocs-sphinx-ext==2.1.4 ; extra == 'docs'
- - recommonmark==0.5.0 ; extra == 'docs'
- - requests==2.25.1 ; extra == 'docs'
- - six==1.15.0 ; extra == 'docs'
- - snowballstemmer==2.1.0 ; extra == 'docs'
- - sphinx-rtd-theme==0.4.3 ; extra == 'docs'
- - sphinx==1.8.5 ; extra == 'docs'
- - sphinxcontrib-serializinghtml==1.1.4 ; extra == 'docs'
- - sphinxcontrib-websupport==1.2.4 ; extra == 'docs'
- - urllib3==1.26.4 ; extra == 'docs'
- - flake8==5.0.4 ; extra == 'qa'
- - mypy==0.971 ; extra == 'qa'
- - types-setuptools==67.2.0.1 ; extra == 'qa'
- - django ; extra == 'testing'
- - attrs ; extra == 'testing'
- - colorama ; extra == 'testing'
- - docopt ; extra == 'testing'
- - pytest<9.0.0 ; extra == 'testing'
- requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
name: joblib
version: 1.5.3
sha256: 5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/bb/f5/fddaec430367be9d62a7ed125530e133bfd4a1c0350fe221149ee0f2b526/jupyter_client-8.7.0-py3-none-any.whl
- name: jupyter-client
- version: 8.7.0
- sha256: 3671a94fd25e62f5f2f554f5e95389c2294d89822378a5f2dd24353e1494a9e0
- requires_dist:
- - jupyter-core>=5.1
- - python-dateutil>=2.8.2
- - pyzmq>=25.0
- - tornado>=6.4.1
- - traitlets>=5.3
- - ipykernel ; extra == 'docs'
- - myst-parser ; extra == 'docs'
- - pydata-sphinx-theme ; extra == 'docs'
- - sphinx-autodoc-typehints ; extra == 'docs'
- - sphinx>=4 ; extra == 'docs'
- - sphinxcontrib-github-alt ; extra == 'docs'
- - sphinxcontrib-spelling ; extra == 'docs'
- - anyio ; extra == 'test'
- - coverage ; extra == 'test'
- - ipykernel>=6.14 ; extra == 'test'
- - mypy ; extra == 'test'
- - paramiko ; sys_platform == 'win32' and extra == 'test'
- - pre-commit ; extra == 'test'
- - pytest ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - pytest-jupyter[client]>=0.6.2 ; extra == 'test'
- - pytest-timeout ; extra == 'test'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl
- name: jupyter-core
- version: 5.9.1
- sha256: ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407
- requires_dist:
- - platformdirs>=2.5
- - traitlets>=5.3
- - intersphinx-registry ; extra == 'docs'
- - myst-parser ; extra == 'docs'
- - pydata-sphinx-theme ; extra == 'docs'
- - sphinx-autodoc-typehints ; extra == 'docs'
- - sphinxcontrib-spelling ; extra == 'docs'
- - traitlets ; extra == 'docs'
- - ipykernel ; extra == 'test'
- - pre-commit ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - pytest-timeout ; extra == 'test'
- - pytest<9 ; extra == 'test'
- requires_python: '>=3.10'
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
name: keras
version: 3.13.0
@@ -1605,18 +1276,6 @@ packages:
- setuptools-scm>=7 ; extra == 'dev'
- setuptools>=64 ; extra == 'dev'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl
- name: matplotlib-inline
- version: 0.2.1
- sha256: d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76
- requires_dist:
- - traitlets
- - flake8 ; extra == 'test'
- - nbdime ; extra == 'test'
- - nbval ; extra == 'test'
- - notebook ; extra == 'test'
- - pytest ; extra == 'test'
- requires_python: '>=3.9'
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
sha256: 9b0037171dad0100f0296699a11ae7d355237b55f42f9094aebc0f41512d96a1
md5: 827064ddfe0de2917fb29f1da4f8f533
@@ -1681,11 +1340,6 @@ packages:
- pylint>=2.6.0 ; extra == 'dev'
- pyink ; extra == 'dev'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- name: mypy-extensions
- version: 1.1.0
- sha256: 1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505
- requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
name: namex
version: 0.1.0
@@ -1718,11 +1372,6 @@ packages:
purls: []
size: 797030
timestamp: 1738196177597
-- pypi: https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl
- name: nest-asyncio
- version: 1.6.0
- sha256: 87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c
- requires_python: '>=3.5'
- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
name: numpy
version: 2.4.0
@@ -2249,71 +1898,6 @@ packages:
- xlsxwriter>=3.0.5 ; extra == 'all'
- zstandard>=0.19.0 ; extra == 'all'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/3a/83/3426f132ed2326c65f7edcd1a4a5a81955f8dba55ebdbcd7026caaa0a1b8/pandera-0.27.1-py3-none-any.whl
- name: pandera
- version: 0.27.1
- sha256: 944838f134035bbc548410943be662379669488e00f3d290ff2c36b6df52665e
- requires_dist:
- - packaging>=20.0
- - pydantic
- - typeguard
- - typing-extensions
- - typing-inspect>=0.6.0
- - numpy>=1.24.4 ; extra == 'pandas'
- - pandas>=2.1.1 ; extra == 'pandas'
- - hypothesis>=6.92.7 ; extra == 'strategies'
- - scipy ; extra == 'hypotheses'
- - pyyaml>=5.1 ; extra == 'io'
- - black ; extra == 'io'
- - frictionless<=4.40.8 ; extra == 'io'
- - pandas-stubs ; extra == 'mypy'
- - scipy-stubs ; python_full_version >= '3.10' and extra == 'mypy'
- - fastapi ; extra == 'fastapi'
- - geopandas<1.1.0 ; extra == 'geopandas'
- - shapely ; extra == 'geopandas'
- - pyspark[connect]>=3.2.0,<4.0.0 ; extra == 'pyspark'
- - modin ; extra == 'modin'
- - ray ; extra == 'modin'
- - dask[dataframe] ; extra == 'modin'
- - distributed ; extra == 'modin'
- - modin ; extra == 'modin-ray'
- - ray ; extra == 'modin-ray'
- - modin ; extra == 'modin-dask'
- - dask[dataframe] ; extra == 'modin-dask'
- - distributed ; extra == 'modin-dask'
- - dask[dataframe] ; extra == 'dask'
- - distributed ; extra == 'dask'
- - ibis-framework>=9.0.0 ; extra == 'ibis'
- - polars>=0.20.0 ; extra == 'polars'
- - hypothesis>=6.92.7 ; extra == 'all'
- - scipy ; extra == 'all'
- - scipy-stubs ; python_full_version >= '3.10' and extra == 'all'
- - pyyaml>=5.1 ; extra == 'all'
- - black ; extra == 'all'
- - frictionless<=4.40.8 ; extra == 'all'
- - pyspark[connect]>=3.2.0,<4.0.0 ; extra == 'all'
- - modin ; extra == 'all'
- - ray ; extra == 'all'
- - dask[dataframe] ; extra == 'all'
- - distributed ; extra == 'all'
- - pandas-stubs ; extra == 'all'
- - fastapi ; extra == 'all'
- - geopandas<1.1.0 ; extra == 'all'
- - shapely ; extra == 'all'
- - ibis-framework>=9.0.0 ; extra == 'all'
- - polars>=0.20.0 ; extra == 'all'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl
- name: parso
- version: 0.8.5
- sha256: 646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887
- requires_dist:
- - pytest ; extra == 'testing'
- - docopt ; extra == 'testing'
- - flake8==5.0.4 ; extra == 'qa'
- - mypy==0.971 ; extra == 'qa'
- - types-setuptools==67.2.0.1 ; extra == 'qa'
- requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
name: patsy
version: 1.0.2
@@ -2324,12 +1908,6 @@ packages:
- pytest-cov ; extra == 'test'
- scipy ; extra == 'test'
requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl
- name: pexpect
- version: 4.9.0
- sha256: 7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523
- requires_dist:
- - ptyprocess>=0.5
- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
name: pillow
version: 12.0.0
@@ -2441,7 +2019,7 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: ce45a3ae37e590d3d8fabac6921a207f1da8cd4a98382b1dfb25f5f145ede0b3
+ sha256: 0865169f67346f5bdcaf3d954ad6f1bf2d3cbbbf9bd60dfa3e5fd74969525f02
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -2451,18 +2029,9 @@ packages:
- joblib>=1.5.3,<2
- statsmodels>=0.14.6,<0.15
- typer>=0.20.0,<0.21
- - pandera>=0.27.1,<0.28
- xgboost>=3.1.2,<4
- optuna>=4.6.0,<5
- - ipykernel>=7.1.0,<8
requires_python: '>=3.11,<3.14'
-- pypi: https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl
- name: prompt-toolkit
- version: 3.0.52
- sha256: 9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955
- requires_dist:
- - wcwidth
- requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
version: 6.33.2
@@ -2478,151 +2047,6 @@ packages:
version: 6.33.2
sha256: d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/10/a1/c75feb480f60cd768fb6ed00ac362a16a33e5076ec8475a22d8162fb2659/psutil-7.2.0-cp36-abi3-macosx_11_0_arm64.whl
- name: psutil
- version: 7.2.0
- sha256: 24151011c21fadd94214d7139d7c6c54569290d7e553989bdf0eab73b13beb8c
- requires_dist:
- - pytest ; extra == 'dev'
- - pytest-instafail ; extra == 'dev'
- - pytest-xdist ; extra == 'dev'
- - setuptools ; extra == 'dev'
- - abi3audit ; extra == 'dev'
- - black ; extra == 'dev'
- - check-manifest ; extra == 'dev'
- - coverage ; extra == 'dev'
- - packaging ; extra == 'dev'
- - pylint ; extra == 'dev'
- - pyperf ; extra == 'dev'
- - pypinfo ; extra == 'dev'
- - pytest-cov ; extra == 'dev'
- - requests ; extra == 'dev'
- - rstcheck ; extra == 'dev'
- - ruff ; extra == 'dev'
- - sphinx ; extra == 'dev'
- - sphinx-rtd-theme ; extra == 'dev'
- - toml-sort ; extra == 'dev'
- - twine ; extra == 'dev'
- - validate-pyproject[all] ; extra == 'dev'
- - virtualenv ; extra == 'dev'
- - vulture ; extra == 'dev'
- - wheel ; extra == 'dev'
- - pytest ; extra == 'test'
- - pytest-instafail ; extra == 'test'
- - pytest-xdist ; extra == 'test'
- - setuptools ; extra == 'test'
- requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/12/ff/e93136587c00a543f4bc768b157fac2c47cd77b180d4f4e5c6efb6ea53a2/psutil-7.2.0-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl
- name: psutil
- version: 7.2.0
- sha256: 91f211ba9279e7c61d9d8f84b713cfc38fa161cb0597d5cb3f1ca742f6848254
- requires_dist:
- - pytest ; extra == 'dev'
- - pytest-instafail ; extra == 'dev'
- - pytest-xdist ; extra == 'dev'
- - setuptools ; extra == 'dev'
- - abi3audit ; extra == 'dev'
- - black ; extra == 'dev'
- - check-manifest ; extra == 'dev'
- - coverage ; extra == 'dev'
- - packaging ; extra == 'dev'
- - pylint ; extra == 'dev'
- - pyperf ; extra == 'dev'
- - pypinfo ; extra == 'dev'
- - pytest-cov ; extra == 'dev'
- - requests ; extra == 'dev'
- - rstcheck ; extra == 'dev'
- - ruff ; extra == 'dev'
- - sphinx ; extra == 'dev'
- - sphinx-rtd-theme ; extra == 'dev'
- - toml-sort ; extra == 'dev'
- - twine ; extra == 'dev'
- - validate-pyproject[all] ; extra == 'dev'
- - virtualenv ; extra == 'dev'
- - vulture ; extra == 'dev'
- - wheel ; extra == 'dev'
- - pytest ; extra == 'test'
- - pytest-instafail ; extra == 'test'
- - pytest-xdist ; extra == 'test'
- - setuptools ; extra == 'test'
- requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/b8/dd/4c2de9c3827c892599d277a69d2224136800870a8a88a80981de905de28d/psutil-7.2.0-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: psutil
- version: 7.2.0
- sha256: f37415188b7ea98faf90fed51131181646c59098b077550246e2e092e127418b
- requires_dist:
- - pytest ; extra == 'dev'
- - pytest-instafail ; extra == 'dev'
- - pytest-xdist ; extra == 'dev'
- - setuptools ; extra == 'dev'
- - abi3audit ; extra == 'dev'
- - black ; extra == 'dev'
- - check-manifest ; extra == 'dev'
- - coverage ; extra == 'dev'
- - packaging ; extra == 'dev'
- - pylint ; extra == 'dev'
- - pyperf ; extra == 'dev'
- - pypinfo ; extra == 'dev'
- - pytest-cov ; extra == 'dev'
- - requests ; extra == 'dev'
- - rstcheck ; extra == 'dev'
- - ruff ; extra == 'dev'
- - sphinx ; extra == 'dev'
- - sphinx-rtd-theme ; extra == 'dev'
- - toml-sort ; extra == 'dev'
- - twine ; extra == 'dev'
- - validate-pyproject[all] ; extra == 'dev'
- - virtualenv ; extra == 'dev'
- - vulture ; extra == 'dev'
- - wheel ; extra == 'dev'
- - pytest ; extra == 'test'
- - pytest-instafail ; extra == 'test'
- - pytest-xdist ; extra == 'test'
- - setuptools ; extra == 'test'
- requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl
- name: ptyprocess
- version: 0.7.0
- sha256: 4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35
-- pypi: https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl
- name: pure-eval
- version: 0.2.3
- sha256: 1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0
- requires_dist:
- - pytest ; extra == 'tests'
-- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl
- name: pydantic
- version: 2.12.5
- sha256: e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d
- requires_dist:
- - annotated-types>=0.6.0
- - pydantic-core==2.41.5
- - typing-extensions>=4.14.1
- - typing-inspection>=0.4.2
- - email-validator>=2.0.0 ; extra == 'email'
- - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- name: pydantic-core
- version: 2.41.5
- sha256: 0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0
- requires_dist:
- - typing-extensions>=4.14.1
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl
- name: pydantic-core
- version: 2.41.5
- sha256: 112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34
- requires_dist:
- - typing-extensions>=4.14.1
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- name: pydantic-core
- version: 2.41.5
- sha256: 406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586
- requires_dist:
- - typing-extensions>=4.14.1
- requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
name: pygments
version: 2.19.2
@@ -2772,27 +2196,6 @@ packages:
version: 6.0.3
sha256: 2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl
- name: pyzmq
- version: 27.1.0
- sha256: 452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc
- requires_dist:
- - cffi ; implementation_name == 'pypy'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl
- name: pyzmq
- version: 27.1.0
- sha256: 43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31
- requires_dist:
- - cffi ; implementation_name == 'pypy'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- name: pyzmq
- version: 27.1.0
- sha256: 3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233
- requires_dist:
- - cffi ; implementation_name == 'pypy'
- requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002
md5: d7d95fc8287ea7bf33e0e7116d2b95ec
@@ -3337,19 +2740,6 @@ packages:
- typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
- sqlcipher3-binary ; extra == 'sqlcipher'
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl
- name: stack-data
- version: 0.6.3
- sha256: d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695
- requires_dist:
- - executing>=1.2.0
- - asttokens>=2.1.0
- - pure-eval
- - pytest ; extra == 'tests'
- - typeguard ; extra == 'tests'
- - pygments ; extra == 'tests'
- - littleutils ; extra == 'tests'
- - cython ; extra == 'tests'
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: statsmodels
version: 0.14.6
@@ -3670,21 +3060,6 @@ packages:
- pkg:pypi/tomlkit?source=hash-mapping
size: 38777
timestamp: 1749127286558
-- pypi: https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- name: tornado
- version: 6.5.4
- sha256: e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl
- name: tornado
- version: 6.5.4
- sha256: d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- name: tornado
- version: 6.5.4
- sha256: d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17
- requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
name: tqdm
version: 4.67.1
@@ -3701,29 +3076,6 @@ packages:
- requests ; extra == 'telegram'
- ipywidgets>=6 ; extra == 'notebook'
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl
- name: traitlets
- version: 5.14.3
- sha256: b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f
- requires_dist:
- - myst-parser ; extra == 'docs'
- - pydata-sphinx-theme ; extra == 'docs'
- - sphinx ; extra == 'docs'
- - argcomplete>=3.0.3 ; extra == 'test'
- - mypy>=1.7.0 ; extra == 'test'
- - pre-commit ; extra == 'test'
- - pytest-mock ; extra == 'test'
- - pytest-mypy-testing ; extra == 'test'
- - pytest>=7.0,<8.2 ; extra == 'test'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl
- name: typeguard
- version: 4.4.4
- sha256: b5f562281b6bfa1f5492470464730ef001646128b180769880468bd84b68b09e
- requires_dist:
- - importlib-metadata>=3.6 ; python_full_version < '3.10'
- - typing-extensions>=4.14.0
- requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
name: typer
version: 0.20.1
@@ -3739,21 +3091,6 @@ packages:
version: 4.15.0
sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
- name: typing-inspect
- version: 0.9.0
- sha256: 9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f
- requires_dist:
- - mypy-extensions>=0.3.0
- - typing-extensions>=3.7.4
- - typing>=3.7.4 ; python_full_version < '3.5'
-- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl
- name: typing-inspection
- version: 0.4.2
- sha256: 4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7
- requires_dist:
- - typing-extensions>=4.12.0
- requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
name: tzdata
version: '2025.3'
@@ -3777,11 +3114,6 @@ packages:
- pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks'
- backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl
- name: wcwidth
- version: 0.2.14
- sha256: a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1
- requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
name: werkzeug
version: 3.1.4
diff --git a/pyproject.toml b/pyproject.toml
index e1687b9..c44201f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,7 +20,8 @@ dependencies = [
"joblib>=1.5.3,<2",
"statsmodels>=0.14.6,<0.15",
"typer>=0.20.0,<0.21",
- "pandera>=0.27.1,<0.28", "xgboost>=3.1.2,<4", "optuna>=4.6.0,<5",
+ "xgboost>=3.1.2,<4",
+ "optuna>=4.6.0,<5",
]
[build-system]
From 03ea2e3319250d454b561e0d297926bcdbe37fdb Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sat, 27 Dec 2025 19:33:00 +0100
Subject: [PATCH 15/50] add multi-arch support to makefile
---
Makefile | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 34cfe8a..39ca759 100644
--- a/Makefile
+++ b/Makefile
@@ -2,14 +2,15 @@ IMAGE_NAME ?= preface
REGISTRY ?= quay.io
USERNAME ?= matthdsm
TAG ?= $(shell sed -n 's/^__version__ = "\(.*\)"/\1/p' src/preface/__init__.py)
+PLATFORMS ?= linux/amd64,linux/arm64
.PHONY: build push bump-version
build:
- docker build -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) .
+ docker buildx build --platform $(PLATFORMS) -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) .
push:
- docker push $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG)
+ docker buildx build --platform $(PLATFORMS) -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) --push .
bump-version:
@if [ -z "$(v)" ]; then echo "Usage: make bump-version v=1.0.0"; exit 1; fi
From 7f7009c4ea88aeb26ab32f60f7e4f4c3ccd8a22d Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 12:52:05 +0100
Subject: [PATCH 16/50] fix docker build
---
Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index 39ca759..32f3f07 100644
--- a/Makefile
+++ b/Makefile
@@ -2,15 +2,15 @@ IMAGE_NAME ?= preface
REGISTRY ?= quay.io
USERNAME ?= matthdsm
TAG ?= $(shell sed -n 's/^__version__ = "\(.*\)"/\1/p' src/preface/__init__.py)
-PLATFORMS ?= linux/amd64,linux/arm64
+PLATFORMS ?= linux/amd64
.PHONY: build push bump-version
-
+
build:
- docker buildx build --platform $(PLATFORMS) -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) .
+ docker build --platform $(PLATFORMS) -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) .
push:
- docker buildx build --platform $(PLATFORMS) -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) --push .
+ docker build --platform $(PLATFORMS) -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) --push .
bump-version:
@if [ -z "$(v)" ]; then echo "Usage: make bump-version v=1.0.0"; exit 1; fi
From ff0498d993f4666cc16aed0e52df2429ef697e23 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 12:52:42 +0100
Subject: [PATCH 17/50] add deps for optuna
---
pixi.lock | 266 ++++++++++++++++++++++++++++++++++++++++++++++++-
pyproject.toml | 3 +
2 files changed, 268 insertions(+), 1 deletion(-)
diff --git a/pixi.lock b/pixi.lock
index 31316ca..f06643c 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -47,6 +47,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
@@ -59,10 +60,13 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
@@ -71,18 +75,25 @@ environments:
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
@@ -92,6 +103,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/43/f1/b392952200f3393bb06fbc4dd975fc63a6843261705839355560b7264eb2/simplejson-3.20.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
@@ -148,6 +160,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
@@ -160,10 +173,13 @@ environments:
- pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
@@ -172,17 +188,24 @@ environments:
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
@@ -192,6 +215,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/09/1d/171009bd35c7099d72ef6afd4bb13527bab469965c968a17d69a203d62a6/simplejson-3.20.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
@@ -242,6 +266,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
@@ -253,10 +278,13 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
@@ -265,17 +293,24 @@ environments:
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
@@ -285,6 +320,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/7a/4d/30dfef83b9ac48afae1cf1ab19c2867e27b8d22b5d9f8ca7ce5a0a157d8c/simplejson-3.20.2-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
@@ -459,6 +495,14 @@ packages:
version: 3.4.4
sha256: a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
+ name: choreographer
+ version: 1.2.1
+ sha256: 9af5385effa3c204dbc337abf7ac74fd8908ced326a15645dc31dde75718c77e
+ requires_dist:
+ - logistro>=2.0.1
+ - simplejson>=3.19.3
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
name: click
version: 8.3.1
@@ -796,6 +840,11 @@ packages:
- pkg:pypi/importlib-metadata?source=hash-mapping
size: 34641
timestamp: 1747934053147
+- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
+ name: iniconfig
+ version: 2.3.0
+ sha256: f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12
+ requires_python: '>=3.10'
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
sha256: 13b0005877f553eb2e5c50447c9d0047e7257124ec2d1569d7dad35697790237
md5: 55a61979242077b2cc377c74326ea9f0
@@ -813,6 +862,17 @@ packages:
version: 1.5.3
sha256: 5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
+ name: kaleido
+ version: 1.2.0
+ sha256: c27ed82b51df6b923d0e656feac221343a0dbcd2fb9bc7e6b1db97f61e9a1513
+ requires_dist:
+ - choreographer>=1.1.1
+ - logistro>=1.0.8
+ - orjson>=3.10.15
+ - packaging
+ - pytest-timeout>=2.4.0
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
name: keras
version: 3.13.0
@@ -1146,6 +1206,11 @@ packages:
purls: []
size: 46438
timestamp: 1727963202283
+- pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
+ name: logistro
+ version: 2.0.1
+ sha256: 06ffa127b9fb4ac8b1972ae6b2a9d7fde57598bf5939cd708f43ec5bba2d31eb
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
name: mako
version: 1.3.10
@@ -1344,6 +1409,26 @@ packages:
name: namex
version: 0.1.0
sha256: e2012a474502f1e2251267062aae3114611f07df4224b6e06334c57b0f2ce87c
+- pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
+ name: narwhals
+ version: 2.14.0
+ sha256: b56796c9a00179bd757d15282c540024e1d5c910b19b8c9944d836566c030acf
+ requires_dist:
+ - cudf>=24.10.0 ; extra == 'cudf'
+ - dask[dataframe]>=2024.8 ; extra == 'dask'
+ - duckdb>=1.1 ; extra == 'duckdb'
+ - ibis-framework>=6.0.0 ; extra == 'ibis'
+ - packaging ; extra == 'ibis'
+ - pyarrow-hotfix ; extra == 'ibis'
+ - rich ; extra == 'ibis'
+ - modin ; extra == 'modin'
+ - pandas>=1.1.3 ; extra == 'pandas'
+ - polars>=0.20.4 ; extra == 'polars'
+ - pyarrow>=13.0.0 ; extra == 'pyarrow'
+ - pyspark>=3.5.0 ; extra == 'pyspark'
+ - pyspark[connect]>=3.5.0 ; extra == 'pyspark-connect'
+ - sqlframe>=3.22.0,!=3.39.3 ; extra == 'sqlframe'
+ requires_python: '>=3.9'
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586
md5: 47e340acb35de30501a76c7c799c41d7
@@ -1620,6 +1705,89 @@ packages:
- grpcio ; extra == 'test'
- protobuf>=5.28.1 ; extra == 'test'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
+ name: optuna-integration
+ version: 4.6.0
+ sha256: a02ef2018c02d521d23e364110579c03e53a518894d9b9a76b246b5fb2e027fd
+ requires_dist:
+ - optuna
+ - pytest ; extra == 'test'
+ - coverage ; extra == 'test'
+ - fakeredis[lua] ; extra == 'test'
+ - grpcio ; extra == 'test'
+ - protobuf>=5.28.1 ; extra == 'test'
+ - black<25.9.0 ; extra == 'checking'
+ - blackdoc<0.4.2 ; extra == 'checking'
+ - hacking ; extra == 'checking'
+ - isort ; extra == 'checking'
+ - mypy ; extra == 'checking'
+ - types-pyyaml ; extra == 'checking'
+ - types-redis ; extra == 'checking'
+ - types-setuptools ; extra == 'checking'
+ - typing-extensions>=3.10.0.0 ; extra == 'checking'
+ - mlflow ; extra == 'document'
+ - pandas ; extra == 'document'
+ - scikit-learn>=0.24.2 ; extra == 'document'
+ - scipy>=1.9.2 ; python_full_version >= '3.9' and extra == 'document'
+ - sphinx ; extra == 'document'
+ - sphinx-notfound-page ; extra == 'document'
+ - sphinx-rtd-theme ; extra == 'document'
+ - allennlp ; extra == 'allennlp'
+ - jsonnet ; extra == 'allennlp'
+ - numpy<2.0.0 ; extra == 'allennlp'
+ - psutil ; extra == 'allennlp'
+ - chainer ; extra == 'chainer'
+ - numpy<2.0.0 ; extra == 'chainer'
+ - chainermn ; extra == 'chainermn'
+ - numpy<2.0.0 ; extra == 'chainermn'
+ - botorch<0.10.0 ; extra == 'botorch'
+ - numpy<2.0.0 ; extra == 'catboost'
+ - catboost ; extra == 'catboost'
+ - numpy<2.0.0 ; extra == 'cma'
+ - cma ; extra == 'cma'
+ - comet-ml>=3.39.3 ; extra == 'comet'
+ - distributed ; extra == 'dask'
+ - fastai>=2.0.0 ; extra == 'fastai'
+ - fastai>=2.0.0 ; extra == 'fastaiv2'
+ - tensorflow ; extra == 'keras'
+ - lightgbm ; extra == 'lightgbm'
+ - scikit-learn ; extra == 'lightgbm'
+ - mlflow ; extra == 'mlflow'
+ - mxnet ; extra == 'mxnet'
+ - gpytorch ; extra == 'pytorch-distributed'
+ - gpytorch ; extra == 'pytorch-distributed'
+ - pytorch-ignite ; extra == 'pytorch-ignite'
+ - pytorch-ignite ; extra == 'pytorch-ignite'
+ - lightning ; extra == 'pytorch-lightning'
+ - lightning ; extra == 'pytorch-lightning'
+ - numpy<2.0.0 ; extra == 'shap'
+ - shap ; extra == 'shap'
+ - pandas ; extra == 'sklearn'
+ - scikit-learn ; extra == 'sklearn'
+ - scipy ; extra == 'sklearn'
+ - skorch ; extra == 'skorch'
+ - tensorboard ; extra == 'tensorboard'
+ - tensorflow ; extra == 'tensorboard'
+ - tensorflow<=2.15.0 ; extra == 'tensorflow'
+ - tensorflow ; extra == 'tfkeras'
+ - wandb ; extra == 'wandb'
+ - xgboost ; extra == 'xgboost'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl
+ name: orjson
+ version: 3.11.5
+ sha256: 3b01799262081a4c47c035dd77c1301d40f568f77cc7ec1bb7db5d63b0a01629
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ name: orjson
+ version: 3.11.5
+ sha256: 894aea2e63d4f24a7f04a1908307c738d0dce992e9249e744b8f4e8dd9197f39
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ name: orjson
+ version: 3.11.5
+ sha256: 75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
name: packaging
version: '25.0'
@@ -2016,10 +2184,61 @@ packages:
- pkg:pypi/platformdirs?source=hash-mapping
size: 23922
timestamp: 1764950726246
+- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
+ name: plotly
+ version: 6.5.0
+ sha256: 5ac851e100367735250206788a2b1325412aa4a4917a4fe3e6f0bc5aa6f3d90a
+ requires_dist:
+ - narwhals>=1.15.1
+ - packaging
+ - numpy ; extra == 'express'
+ - kaleido>=1.1.0 ; extra == 'kaleido'
+ - pytest ; extra == 'dev-core'
+ - requests ; extra == 'dev-core'
+ - ruff==0.11.12 ; extra == 'dev-core'
+ - plotly[dev-core] ; extra == 'dev-build'
+ - build ; extra == 'dev-build'
+ - jupyter ; extra == 'dev-build'
+ - plotly[dev-build] ; extra == 'dev-optional'
+ - plotly[kaleido] ; extra == 'dev-optional'
+ - anywidget ; extra == 'dev-optional'
+ - colorcet ; extra == 'dev-optional'
+ - fiona<=1.9.6 ; python_full_version < '3.9' and extra == 'dev-optional'
+ - geopandas ; extra == 'dev-optional'
+ - inflect ; extra == 'dev-optional'
+ - numpy ; extra == 'dev-optional'
+ - orjson ; extra == 'dev-optional'
+ - pandas ; extra == 'dev-optional'
+ - pdfrw ; extra == 'dev-optional'
+ - pillow ; extra == 'dev-optional'
+ - plotly-geo ; extra == 'dev-optional'
+ - polars[timezone] ; extra == 'dev-optional'
+ - pyarrow ; extra == 'dev-optional'
+ - pyshp ; extra == 'dev-optional'
+ - pytz ; extra == 'dev-optional'
+ - scikit-image ; extra == 'dev-optional'
+ - scipy ; extra == 'dev-optional'
+ - shapely ; extra == 'dev-optional'
+ - statsmodels ; extra == 'dev-optional'
+ - vaex ; python_full_version < '3.10' and extra == 'dev-optional'
+ - xarray ; extra == 'dev-optional'
+ - plotly[dev-optional] ; extra == 'dev'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
+ name: pluggy
+ version: 1.6.0
+ sha256: e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
+ requires_dist:
+ - pre-commit ; extra == 'dev'
+ - tox ; extra == 'dev'
+ - pytest ; extra == 'testing'
+ - pytest-benchmark ; extra == 'testing'
+ - coverage ; extra == 'testing'
+ requires_python: '>=3.9'
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: 0865169f67346f5bdcaf3d954ad6f1bf2d3cbbbf9bd60dfa3e5fd74969525f02
+ sha256: 797b90c4b49edc0c99285bb9f62e8343955d46112b9ea3688ae8d488fcdfdd1d
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -2031,6 +2250,9 @@ packages:
- typer>=0.20.0,<0.21
- xgboost>=3.1.2,<4
- optuna>=4.6.0,<5
+ - optuna-integration[tfkeras]>=4.6.0,<5
+ - plotly>=6.5.0,<7
+ - kaleido>=1.2.0,<2
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
@@ -2082,6 +2304,33 @@ packages:
- railroad-diagrams ; extra == 'diagrams'
- jinja2 ; extra == 'diagrams'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
+ name: pytest
+ version: 9.0.2
+ sha256: 711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b
+ requires_dist:
+ - colorama>=0.4 ; sys_platform == 'win32'
+ - exceptiongroup>=1 ; python_full_version < '3.11'
+ - iniconfig>=1.0.1
+ - packaging>=22
+ - pluggy>=1.5,<2
+ - pygments>=2.7.2
+ - tomli>=1 ; python_full_version < '3.11'
+ - argcomplete ; extra == 'dev'
+ - attrs>=19.2 ; extra == 'dev'
+ - hypothesis>=3.56 ; extra == 'dev'
+ - mock ; extra == 'dev'
+ - requests ; extra == 'dev'
+ - setuptools ; extra == 'dev'
+ - xmlschema ; extra == 'dev'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
+ name: pytest-timeout
+ version: 2.4.0
+ sha256: c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2
+ requires_dist:
+ - pytest>=7.0.0
+ requires_python: '>=3.7'
- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.11-hc97d973_100_cp313.conda
build_number: 100
sha256: 9cf014cf28e93ee242bacfbf664e8b45ae06e50b04291e640abeaeb0cba0364c
@@ -2621,6 +2870,21 @@ packages:
version: 1.5.4
sha256: 7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686
requires_python: '>=3.7'
+- pypi: https://files.pythonhosted.org/packages/09/1d/171009bd35c7099d72ef6afd4bb13527bab469965c968a17d69a203d62a6/simplejson-3.20.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ name: simplejson
+ version: 3.20.2
+ sha256: 552f55745044a24c3cb7ec67e54234be56d5d6d0e054f2e4cf4fb3e297429be5
+ requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/43/f1/b392952200f3393bb06fbc4dd975fc63a6843261705839355560b7264eb2/simplejson-3.20.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ name: simplejson
+ version: 3.20.2
+ sha256: 133ae2098a8e162c71da97cdab1f383afdd91373b7ff5fe65169b04167da976b
+ requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/7a/4d/30dfef83b9ac48afae1cf1ab19c2867e27b8d22b5d9f8ca7ce5a0a157d8c/simplejson-3.20.2-cp313-cp313-macosx_11_0_arm64.whl
+ name: simplejson
+ version: 3.20.2
+ sha256: 6b1d8d7c3e1a205c49e1aee6ba907dcb8ccea83651e6c3e2cb2062f1e52b0726
+ requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
name: six
version: 1.17.0
diff --git a/pyproject.toml b/pyproject.toml
index c44201f..e1b4ed0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -22,6 +22,9 @@ dependencies = [
"typer>=0.20.0,<0.21",
"xgboost>=3.1.2,<4",
"optuna>=4.6.0,<5",
+ "optuna-integration[tfkeras]>=4.6.0,<5",
+ "plotly>=6.5.0,<7",
+ "kaleido>=1.2.0,<2",
]
[build-system]
From 872660b4cb552f1f2989a074c8b49c973a196201 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 13:25:27 +0100
Subject: [PATCH 18/50] bugfixes
---
src/preface/lib/neural.py | 17 ++++++++---------
src/preface/lib/xgboost.py | 8 ++++----
src/preface/train.py | 8 +++++---
3 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index ab12a3d..7389808 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -15,7 +15,7 @@ def neural_tune(features: npt.NDArray, targets: npt.NDArray, outdir: Path) -> di
def objective(trial) -> float:
params = {
"n_layers": trial.suggest_int("n_layers", 1, 3),
- "hidden_size": trial.suggest_int("hidden_size", 16, 128, step=32),
+ "hidden_size": trial.suggest_int("hidden_size", 16, 128, step=16),
"learning_rate": trial.suggest_float("learning_rate", 1e-4, 1e-2, log=True),
"dropout_rate": trial.suggest_float("dropout_rate", 0.1, 0.5, step=0.1),
}
@@ -41,6 +41,7 @@ def objective(trial) -> float:
callbacks=[
optuna.integration.TFKerasPruningCallback(trial, "val_loss")
],
+ verbose=True
)
scores.append(min((history.history["val_loss"])))
@@ -51,9 +52,8 @@ def objective(trial) -> float:
)
study.optimize(objective, n_trials=30)
- optuna.visualization.plot_optimization_history(study).savefig(
- outdir / "neural_tuning_history.png"
- )
+ fig = optuna.visualization.plot_optimization_history(study)
+ fig.write_image(outdir / "neural_tuning_history.png")
return study.best_params
@@ -65,8 +65,8 @@ def multi_output_nn(
dropout_rate: float,
) -> Model:
x = layers.Input(shape=(input_dim,))
- for _ in range(n_layers):
- x = layers.Dense(hidden_size, activation="relu")(x)
+ for i in range(n_layers):
+ x = layers.Dense(hidden_size // (2 ** i), activation="relu")(x)
x = layers.Dropout(dropout_rate)(x)
# Head 1: Regression
@@ -91,7 +91,6 @@ def neural_fit(
y_train_class: npt.NDArray,
y_test_reg: npt.NDArray,
y_test_class: npt.NDArray,
- input_dim: int,
params: dict,
) -> tuple[Model, dict]:
"""Build a multi-output neural network for regression and classification."""
@@ -109,7 +108,7 @@ def neural_fit(
)
# Create model
- model = multi_output_nn(input_dim=input_dim, **{**nn_default_params, **params})
+ model = multi_output_nn(input_dim=x_train.shape[1], **{**nn_default_params, **params})
# Fit model
model.fit(
@@ -121,7 +120,7 @@ def neural_fit(
),
epochs=100,
batch_size=32,
- verbose=1,
+ verbose=True,
callbacks=[early_stop],
)
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 9317501..b0b5ad0 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -41,9 +41,8 @@ def objective(trial) -> float:
study = optuna.create_study(direction="minimize")
study.optimize(objective, n_trials=30)
- optuna.visualization.plot_optimization_history(study).savefig(
- outdir / "xgboost_tuning_history.png"
- )
+ fig = optuna.visualization.plot_optimization_history(study)
+ fig.write_image(outdir / "xgboost_tuning_history.png")
return study.best_params
@@ -70,9 +69,10 @@ def xgboost_fit(
model = XGBRegressor(
**{**xgb_default_params, **params} # Merge default and tuned parameters
)
+ model._estimator_type = "regressor" # type: ignore
# Fit model
- model.fit(x_train, y_train, eval_set=[(x_test, y_test)], verbose=False)
+ model.fit(x_train, y_train, eval_set=[(x_test, y_test)])
# Evaluate
preds = model.predict(x_test)
diff --git a/src/preface/train.py b/src/preface/train.py
index 50fc33d..7ab5410 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -123,7 +123,7 @@ def preface_train(
# add sample metadata columns to transposed ratios
masked_ratios["id"] = sample["ID"]
- masked_ratios["sex"] = sample["sex"].map({"M": 1, "F": 0})
+ masked_ratios["sex"] = 1 if sample["sex"] == "M" else 0
masked_ratios["ff"] = sample["FF"]
# add to list
@@ -176,6 +176,7 @@ def preface_train(
y_sex_all = y_all["sex"]
# Reduce dimensionality with PCA
+ logging.info("Calculating Principal Components")
global_pca = PCA(n_components=n_feat)
x_all_pca = global_pca.fit_transform(x_all)
@@ -218,13 +219,14 @@ def preface_train(
n_feat,
params,
)
+ # Save fold model
+ model.save(out_dir / "training_folds" / f"fold_{fold}.keras") # type: ignore
+
elif model == ModelOptions.XGBOOST:
model, predictions = xgboost_fit(
x_train, x_test, y_train.to_numpy(), y_test.to_numpy(), params
)
- # Save fold model
- model.save(out_dir / "training_folds" / f"fold_{fold}.keras") # type: ignore
fold_models.append(model)
# Plot regression performance
From 40ccce37da2f0f20e8a390309dd9cd18d43cc536 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 15:18:28 +0100
Subject: [PATCH 19/50] Build docker with fixed locked versions
---
Dockerfile | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index dd50fe6..dee425c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,9 +1,24 @@
+# Stage 1: Build environment
+FROM ghcr.io/prefix-dev/pixi:latest AS build
+
+# Copy everything for the build
+COPY . /app
+WORKDIR /app
+
+# Install dependencies and the project non-editable
+RUN pixi install --frozen --locked
+RUN pixi run pip install --no-deps .
+
+# Stage 2: Runtime
FROM python:3.13-slim
WORKDIR /app
-COPY . /app
+# Copy only the installed environment from the build stage
+COPY --from=build /app/.pixi/envs/default /app/.pixi/envs/default
-RUN pip install --no-cache-dir .
+# Set path to use the pixi environment
+ENV PATH="/app/.pixi/envs/default/bin:$PATH"
+# Set entrypoint
ENTRYPOINT ["PREFACE"]
\ No newline at end of file
From 1e4397d1c08680fab61243d9497892923b2af387 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 15:19:54 +0100
Subject: [PATCH 20/50] add deps, fix linting
---
pixi.lock | 172 +++++++++++++++++++++++++++-
pyproject.toml | 5 +
src/preface/utils/npz_to_parquet.py | 3 +-
3 files changed, 177 insertions(+), 3 deletions(-)
diff --git a/pixi.lock b/pixi.lock
index f06643c..54415ae 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -49,6 +49,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
@@ -59,6 +60,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
@@ -74,10 +76,15 @@ environments:
- pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/84/a7/38aa564871d062c11538d65c575af9c7e057be880c09ecbd899dd1abfa83/onnx-1.20.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/f2/2b/b57c8a2466a3126dbe0a792f56ad7290949b02f47b86216cd47d857e4b77/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
@@ -105,8 +112,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/f1/b392952200f3393bb06fbc4dd975fc63a6843261705839355560b7264eb2/simplejson-3.20.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
@@ -162,6 +171,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
@@ -172,6 +182,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
@@ -187,9 +198,14 @@ environments:
- pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/78/bb/b98732309f2f6beb4cdcf7b955d7bbfd75a191185370ee21233373db381e/onnx-1.20.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/1c/a1/428ee29c6eaf09a6f6be56f836213f104618fb35ac6cc586ff0f477263eb/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
@@ -217,8 +233,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/1d/171009bd35c7099d72ef6afd4bb13527bab469965c968a17d69a203d62a6/simplejson-3.20.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
@@ -268,6 +286,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
@@ -277,6 +296,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
@@ -292,9 +312,14 @@ environments:
- pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/5e/19/2caa972a31014a8cb4525f715f2a75d93caef9d4b9da2809cc05d0489e43/onnx-1.20.0-cp312-abi3-macosx_12_0_universal2.whl
+ - pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/3d/41/fba0cabccecefe4a1b5fc8020c44febb334637f133acefc7ec492029dd2c/onnxruntime-1.23.2-cp313-cp313-macosx_13_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
@@ -322,8 +347,10 @@ environments:
- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/4d/30dfef83b9ac48afae1cf1ab19c2867e27b8d22b5d9f8ca7ce5a0a157d8c/simplejson-3.20.2-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
@@ -521,6 +548,14 @@ packages:
- pkg:pypi/colorama?source=hash-mapping
size: 27011
timestamp: 1733218222191
+- pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
+ name: coloredlogs
+ version: 15.0.1
+ sha256: 612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934
+ requires_dist:
+ - humanfriendly>=9.1
+ - capturer>=2.4 ; extra == 'cron'
+ requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*'
- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
name: colorlog
version: 6.10.1
@@ -817,6 +852,15 @@ packages:
requires_dist:
- numpy>=1.21.2
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
+ name: humanfriendly
+ version: '10.0'
+ sha256: 1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477
+ requires_dist:
+ - monotonic ; python_full_version == '2.7.*'
+ - pyreadline ; python_full_version < '3.8' and sys_platform == 'win32'
+ - pyreadline3 ; python_full_version >= '3.8' and sys_platform == 'win32'
+ requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*'
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
name: idna
version: '3.11'
@@ -1405,6 +1449,19 @@ packages:
- pylint>=2.6.0 ; extra == 'dev'
- pyink ; extra == 'dev'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
+ name: mpmath
+ version: 1.3.0
+ sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c
+ requires_dist:
+ - pytest>=4.6 ; extra == 'develop'
+ - pycodestyle ; extra == 'develop'
+ - pytest-cov ; extra == 'develop'
+ - codecov ; extra == 'develop'
+ - wheel ; extra == 'develop'
+ - sphinx ; extra == 'docs'
+ - gmpy2>=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy'
+ - pytest>=4.6 ; extra == 'tests'
- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
name: namex
version: 0.1.0
@@ -1477,6 +1534,97 @@ packages:
version: 2.28.9
sha256: 485776daa8447da5da39681af455aa3b2c2586ddcf4af8772495e7c532c7e5ab
requires_python: '>=3'
+- pypi: https://files.pythonhosted.org/packages/5e/19/2caa972a31014a8cb4525f715f2a75d93caef9d4b9da2809cc05d0489e43/onnx-1.20.0-cp312-abi3-macosx_12_0_universal2.whl
+ name: onnx
+ version: 1.20.0
+ sha256: 31efe37d7d1d659091f34ddd6a31780334acf7c624176832db9a0a8ececa8fb5
+ requires_dist:
+ - numpy>=1.23.2
+ - protobuf>=4.25.1
+ - typing-extensions>=4.7.1
+ - ml-dtypes>=0.5.0
+ - pillow ; extra == 'reference'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/78/bb/b98732309f2f6beb4cdcf7b955d7bbfd75a191185370ee21233373db381e/onnx-1.20.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
+ name: onnx
+ version: 1.20.0
+ sha256: d75da05e743eb9a11ff155a775cae5745e71f1cd0ca26402881b8f20e8d6e449
+ requires_dist:
+ - numpy>=1.23.2
+ - protobuf>=4.25.1
+ - typing-extensions>=4.7.1
+ - ml-dtypes>=0.5.0
+ - pillow ; extra == 'reference'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/84/a7/38aa564871d062c11538d65c575af9c7e057be880c09ecbd899dd1abfa83/onnx-1.20.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: onnx
+ version: 1.20.0
+ sha256: 02e0d72ab09a983fce46686b155a5049898558d9f3bc6e8515120d6c40666318
+ requires_dist:
+ - numpy>=1.23.2
+ - protobuf>=4.25.1
+ - typing-extensions>=4.7.1
+ - ml-dtypes>=0.5.0
+ - pillow ; extra == 'reference'
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
+ name: onnxconverter-common
+ version: 1.16.0
+ sha256: df39ee96f17fff119dff10dd245467651b60b9e8a96020eb93402239794852f7
+ requires_dist:
+ - numpy
+ - onnx
+ - packaging
+ - protobuf>=3.20.2
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - ruff ; extra == 'lint'
+ - pyright ; extra == 'lint'
+ - onnxconverter-common[lint,test] ; extra == 'dev'
+ requires_python: '>=3.8'
+- pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
+ name: onnxmltools
+ version: 1.14.0
+ sha256: 8036cdcc16d50cf91fe7470d4a91a5bd7d2006170d052b051f33287aa7615252
+ requires_dist:
+ - numpy
+ - onnx
+- pypi: https://files.pythonhosted.org/packages/1c/a1/428ee29c6eaf09a6f6be56f836213f104618fb35ac6cc586ff0f477263eb/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ name: onnxruntime
+ version: 1.23.2
+ sha256: 45d127d6e1e9b99d1ebeae9bcd8f98617a812f53f46699eafeb976275744826b
+ requires_dist:
+ - coloredlogs
+ - flatbuffers
+ - numpy>=1.21.6
+ - packaging
+ - protobuf
+ - sympy
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/3d/41/fba0cabccecefe4a1b5fc8020c44febb334637f133acefc7ec492029dd2c/onnxruntime-1.23.2-cp313-cp313-macosx_13_0_arm64.whl
+ name: onnxruntime
+ version: 1.23.2
+ sha256: 2ff531ad8496281b4297f32b83b01cdd719617e2351ffe0dba5684fb283afa1f
+ requires_dist:
+ - coloredlogs
+ - flatbuffers
+ - numpy>=1.21.6
+ - packaging
+ - protobuf
+ - sympy
+ requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/f2/2b/b57c8a2466a3126dbe0a792f56ad7290949b02f47b86216cd47d857e4b77/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ name: onnxruntime
+ version: 1.23.2
+ sha256: 8bace4e0d46480fbeeb7bbe1ffe1f080e6663a42d1086ff95c1551f2d39e7872
+ requires_dist:
+ - coloredlogs
+ - flatbuffers
+ - numpy>=1.21.6
+ - packaging
+ - protobuf
+ - sympy
+ requires_python: '>=3.10'
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d
md5: 9ee58d5c534af06558933af3c845a780
@@ -2238,7 +2386,7 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: 797b90c4b49edc0c99285bb9f62e8343955d46112b9ea3688ae8d488fcdfdd1d
+ sha256: a62ce1d73d0b5581dc96ae08f3ce585615d07cc5f48eb209b2e1c42a450cedab
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -2253,6 +2401,11 @@ packages:
- optuna-integration[tfkeras]>=4.6.0,<5
- plotly>=6.5.0,<7
- kaleido>=1.2.0,<2
+ - onnx>=1.20.0,<2
+ - onnxmltools>=1.14.0,<2
+ - skl2onnx>=1.19.1,<2
+ - onnxconverter-common>=1.16.0,<2
+ - onnxruntime
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
@@ -2890,6 +3043,14 @@ packages:
version: 1.17.0
sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
+ name: skl2onnx
+ version: 1.19.1
+ sha256: fddf2f49e3ffc355f332e676b43c6fec5e63797627925b279d9f5b2c4d0c81a7
+ requires_dist:
+ - onnx>=1.2.1
+ - scikit-learn>=1.1
+ requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
name: sqlalchemy
version: 2.0.45
@@ -3106,6 +3267,15 @@ packages:
- numpydoc ; extra == 'docs'
- pandas-datareader ; extra == 'docs'
requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
+ name: sympy
+ version: 1.14.0
+ sha256: e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5
+ requires_dist:
+ - mpmath>=1.1.0,<1.4
+ - pytest>=7.1.0 ; extra == 'dev'
+ - hypothesis>=6.70.0 ; extra == 'dev'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
name: tensorboard
version: 2.20.0
diff --git a/pyproject.toml b/pyproject.toml
index e1b4ed0..3c03fa6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -25,6 +25,11 @@ dependencies = [
"optuna-integration[tfkeras]>=4.6.0,<5",
"plotly>=6.5.0,<7",
"kaleido>=1.2.0,<2",
+ "onnx>=1.20.0,<2",
+ "onnxmltools>=1.14.0,<2",
+ "skl2onnx>=1.19.1,<2",
+ "onnxconverter-common>=1.16.0,<2",
+ "onnxruntime>=1.23.2,<2",
]
[build-system]
diff --git a/src/preface/utils/npz_to_parquet.py b/src/preface/utils/npz_to_parquet.py
index 4f61607..0831e9c 100644
--- a/src/preface/utils/npz_to_parquet.py
+++ b/src/preface/utils/npz_to_parquet.py
@@ -4,7 +4,6 @@
import logging
import os
-from typing import List
import numpy as np
import pandas as pd
@@ -69,7 +68,7 @@ def _convert_single_npz(npz_path: str, output_dir: str) -> None:
def npz_to_parquet(
- npz_files: List[str] = typer.Argument(
+ npz_files: list[str] = typer.Argument(
..., help="One or more .npz files to convert."
),
output_dir: str = typer.Option(
From 514720d8feaf692cc779d2b23df1701538736398 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 15:20:28 +0100
Subject: [PATCH 21/50] migrate ensemble model to onnx, move pca to CV
---
src/preface/lib/ensemble.py | 98 +++++++++++++++++++++++++++++++
src/preface/lib/functions.py | 57 +-----------------
src/preface/lib/neural.py | 9 ++-
src/preface/lib/xgboost.py | 12 +++-
src/preface/predict.py | 22 ++++---
src/preface/train.py | 111 ++++++++++++++++++-----------------
6 files changed, 187 insertions(+), 122 deletions(-)
create mode 100644 src/preface/lib/ensemble.py
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
new file mode 100644
index 0000000..7977c23
--- /dev/null
+++ b/src/preface/lib/ensemble.py
@@ -0,0 +1,98 @@
+from pathlib import Path
+
+import onnx
+import onnxmltools
+from onnx import TensorProto, ModelProto, GraphProto, FunctionProto, helper
+from onnx.compose import add_prefix, merge_models
+from skl2onnx import convert_sklearn
+from skl2onnx.common.data_types import FloatTensorType
+from sklearn.decomposition import PCA
+from tensorflow.keras import Model # type: ignore
+from xgboost import XGBRegressor
+
+
+def build_ensemble(
+ pca_obj: PCA, models: list[Model | XGBRegressor], input_dim: int, output_path: Path
+) -> tuple[ModelProto | GraphProto | FunctionProto]:
+ """
+ Save an ensemble of models (either Keras NNs or XGBoost regressors) combined with a PCA
+ """
+
+ initial_type = [("input", FloatTensorType([None, input_dim]))]
+ pca_onnx = convert_sklearn(pca_obj, initial_types=initial_type, target_opset=12)
+ pca_out_name = pca_onnx.graph.output[0].name # type: ignore
+
+ prefixed_models = []
+ model_type = "nn" if isinstance(models[0], Model) else "xgb"
+ for i, m in enumerate(models):
+ if model_type == "nn":
+ m_onnx = onnxmltools.convert_keras(m, name=f"fold_{i}")
+ elif model_type == "xgb":
+ m_onnx = onnxmltools.convert_xgboost(
+ m,
+ initial_types=[
+ (pca_out_name, FloatTensorType([None, pca_obj.n_components_]))
+ ],
+ )
+ else:
+ raise ValueError("Model must be either Keras Model or XGBRegressor")
+
+ # Prefixing prevents node name collisions between the 10 folds
+ prefixed_models.append(add_prefix(m_onnx, prefix=f"fold_{i}_"))
+
+ # --- 2. Merge Graphs ---
+ combined_model = pca_onnx
+ for i in range(len(prefixed_models)):
+ combined_model = merge_models(
+ combined_model, # type: ignore
+ prefixed_models[i],
+ io_map=[(pca_out_name, f"fold_{i}_{pca_out_name}")],
+ )
+
+ graph = combined_model.graph # type: ignore
+
+ # --- 3. Identify Output Names for Averaging ---
+ # For NN: Keras usually names outputs after the final layer (e.g., 'reg_out', 'class_out')
+ # For XGB: Multi-output trees usually output a single tensor that we must split
+ if model_type == "nn":
+ reg_names = [f"fold_{i}_reg_output" for i in range(len(models))]
+ class_names = [f"fold_{i}_class_output" for i in range(len(models))]
+ else:
+ # XGB strategy: We split the combined output tensor [Batch, 2] into two
+ reg_names, class_names = [], []
+ for i in range(len(models)):
+ reg_node_out = f"fold_{i}_reg_split"
+ class_node_out = f"fold_{i}_class_split"
+ reg_names.append(reg_node_out)
+ class_names.append(class_node_out)
+
+ # --- 4. Add Mean Nodes for both heads ---
+ final_reg_name = "final_ff_score"
+ final_class_name = "final_sex_prob"
+
+ mean_reg_node = helper.make_node(
+ "Mean", inputs=reg_names, outputs=[final_reg_name], name="Mean_FF"
+ )
+ mean_class_node = helper.make_node(
+ "Mean", inputs=class_names, outputs=[final_class_name], name="Mean_Sex"
+ )
+
+ graph.node.extend([mean_reg_node, mean_class_node])
+
+ # --- 5. Clean up and finalize outputs ---
+ while len(graph.output) > 0:
+ graph.output.pop()
+
+ graph.output.extend(
+ [
+ helper.make_tensor_value_info(final_reg_name, TensorProto.FLOAT, [None, 1]),
+ helper.make_tensor_value_info(
+ final_class_name, TensorProto.FLOAT, [None, 1]
+ ),
+ ]
+ )
+
+ onnx.save(combined_model, output_path) # type: ignore
+ print(f"Dual-head ensemble saved to {output_path}")
+
+ return combined_model # type: ignore
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index c99d49b..e1f96eb 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -4,14 +4,9 @@
import numpy as np
import pandas as pd
import statsmodels.api as sm
-import tensorflow as tf
-from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
-from tensorflow.keras import ( # pylint: disable=no-name-in-module,import-error # type: ignore
- Model,
- layers,
-)
+
COLOR_A: str = "#8DD1C6"
COLOR_B: str = "#E3C88A"
@@ -38,56 +33,6 @@ def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.Da
return ratios_df
-def build_ensemble(n_feat: int, pca: PCA, models: list[Model]) -> Model:
- """
- Build an ensemble model that averages predictions from multiple fold models.
- Each fold model is assumed to have two outputs: regression and classification.
- """
-
- # Add input layer
- ensemble_input = layers.Input(shape=(n_feat,), name="input")
-
- # Add PCA layer
- class PCALayer(layers.Layer):
- def __init__(self, pca, **kwargs):
- super(
- PCALayer,
- self,
- ).__init__(**kwargs)
- # Convert Scikit-Learn attributes to TensorFlow constants
- self.components = tf.constant(pca.components_.T, dtype=tf.float32)
-
- def call(self, inputs):
- # PCA: Matrix multiplication with components
- pca_data = tf.matmul(inputs, self.components)
- return pca_data
-
- pca_feat = PCALayer(pca, name="pca")(ensemble_input)
-
- # Add each fold model as a sub-network
- reg_outputs = []
- class_outputs = []
-
- for i, fold_model in enumerate(models):
- fold_model.name = f"fold_model_{i}" # Ensure unique names
-
- # Pass the PCA features through the fold model
- reg_out, class_out = fold_model(pca_feat)
- reg_outputs.append(reg_out)
- class_outputs.append(class_out)
-
- # Average regression outputs
- avg_reg_output = layers.Average(name="ff_pred")(reg_outputs)
- avg_class_output = layers.Average(name="sex_pred")(class_outputs)
-
- # Build and return ensemble model
- return Model(
- inputs=ensemble_input,
- outputs=[avg_reg_output, avg_class_output],
- name="PREFACE_model",
- )
-
-
def plot_regression_performance(
y_pred: np.ndarray,
y_true: np.ndarray,
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 7389808..1fcf627 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -3,6 +3,7 @@
import numpy as np
import numpy.typing as npt
import optuna
+from sklearn.decomposition import PCA
from sklearn.model_selection import KFold
from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
from tensorflow.keras import ( # pylint: disable=no-name-in-module,import-error # type: ignore
@@ -11,7 +12,7 @@
)
-def neural_tune(features: npt.NDArray, targets: npt.NDArray, outdir: Path) -> dict:
+def neural_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path) -> dict:
def objective(trial) -> float:
params = {
"n_layers": trial.suggest_int("n_layers", 1, 3),
@@ -25,8 +26,12 @@ def objective(trial) -> float:
scores = []
for t_idx, v_idx in kf_internal.split(features):
+ # reduce dimensionality with PCA
+ pca = PCA(n_components=n_components)
+ features_pca = pca.fit_transform(features)
+
model = multi_output_nn(
- input_dim=features.shape[1],
+ input_dim=features_pca.shape[1],
n_layers=params["n_layers"],
hidden_size=params["hidden_size"],
learning_rate=params["learning_rate"],
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index b0b5ad0..b15cdd0 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -8,9 +8,10 @@
Model,
)
from xgboost import XGBRegressor
+from sklearn.decomposition import PCA
-def xgboost_tune(features: npt.NDArray, targets: npt.NDArray, outdir: Path) -> dict:
+def xgboost_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path) -> dict:
def objective(trial) -> float:
params = {
# number of boosting rounds
@@ -32,9 +33,14 @@ def objective(trial) -> float:
scores = []
for t_idx, v_idx in kf_internal.split(features):
+ # Reduce dimensionality with PCA
+ pca = PCA(n_components=n_components)
+ features_pca = pca.fit_transform(features)
+
+ # Train and evaluate model
model = XGBRegressor(**params)
- model.fit(features[t_idx], targets[t_idx])
- preds = model.predict(features[v_idx])
+ model.fit(features_pca[t_idx], targets[t_idx])
+ preds = model.predict(features_pca[v_idx])
scores.append(mean_squared_error(targets[v_idx], preds))
return np.mean(scores).astype(float)
diff --git a/src/preface/predict.py b/src/preface/predict.py
index d5d4aa4..db9ba94 100644
--- a/src/preface/predict.py
+++ b/src/preface/predict.py
@@ -4,22 +4,23 @@
import pandas as pd
import typer
-from tensorflow.keras.saving import load_model # pylint: disable=no-name-in-module,import-error # type: ignore
from preface.lib.functions import preprocess_ratios
from rich import print
+from pathlib import Path
+import onnxruntime as ort
def preface_predict(
- infile: str = typer.Option(..., "--infile", help="Path to input BED file"),
- model_path: str = typer.Option(..., "--model", help="Path to model"),
+ infile: Path = typer.Option(..., "--infile", help="Path to input BED file"),
+ model_path: Path = typer.Option(..., "--model", help="Path to model"),
) -> None:
"""
Predict using model.
"""
# Load model
- preface_model = load_model(model_path)
- ratios = pd.read_csv(infile, sep="\t")
+ preface_model: ort.InferenceSession = ort.InferenceSession(model_path)
+ ratios: pd.DataFrame = pd.read_csv(infile, sep="\t")
# Preprocess ratios
preprocessed_ratios = preprocess_ratios(ratios, exclude_chrs=[])
@@ -31,9 +32,14 @@ def preface_predict(
# else:
# x_ratio = float(np.nan)
- ff_pred, sex_pred = preface_model.predict(preprocessed_ratios.values)
- print(f"FF = {ff_pred:.4g}%")
- print(f"Sex = {sex_pred}")
+ results = preface_model.run(None, {preface_model.get_inputs()[0].name: preprocessed_ratios.values})
+ ff_score = results[0][0][0] # type: ignore
+ sex_prob = results[1][0][0] # type: ignore
+ sex_class = "Male" if sex_prob > 0.5 else "Female"
+
+ print("--- Patient Report ---")
+ print(f"Predicted FF Score: {ff_score:.4f}")
+ print(f"Sex Probability: {sex_prob:.4f} ({sex_class})")
# ffx: float = (x_ratio - intercept_x) / slope_x
diff --git a/src/preface/train.py b/src/preface/train.py
index 7ab5410..bc74e5f 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -3,14 +3,14 @@
"""
import os
-import time
+# import time
from pathlib import Path
import logging
-
from enum import Enum
import pandas as pd
import typer
import sklearn
+import numpy.typing as npt
from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
from sklearn.impute import IterativeImputer
from sklearn.decomposition import PCA
@@ -19,13 +19,13 @@
from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
from preface.lib.functions import (
- build_ensemble,
plot_regression_performance,
plot_classification_performance,
preprocess_ratios,
)
from preface.lib.xgboost import xgboost_tune, xgboost_fit
from preface.lib.neural import neural_tune, neural_fit
+# from preface.lib.ensemble import build_ensemble
# Constants
EXCLUDE_CHRS: list[str] = ["13", "18", "21", "X", "Y"]
@@ -73,7 +73,7 @@ def preface_train(
"""
Train and optionally tune the PREFACE model.
"""
- start_time: float = time.time()
+ # start_time: float = time.time()
# Load samplesheet
samplesheet_data: pd.DataFrame = pd.read_csv(
@@ -154,9 +154,12 @@ def preface_train(
logging.info("Imputing missing values using MICE... This might take a while.")
imputer = IterativeImputer(
- random_state=42, max_iter=10, initial_strategy="mean", verbose=1
+ random_state=42, max_iter=10, initial_strategy="mean", verbose=2
)
+ logging.info("Fitting imputer to data...")
training_df_array = imputer.fit_transform(ratios_per_sample)
+ logging.info(f"Imputation completed. Sample of imputed data:\n{training_df_array[:10]}")
+
ratios_per_sample = pd.DataFrame(
training_df_array,
index=ratios_per_sample.index,
@@ -168,26 +171,26 @@ def preface_train(
ratios_per_sample = ratios_per_sample.fillna(0.0)
# Split into features and labels
- x_all: pd.DataFrame = ratios_per_sample.drop(columns=["sex", "ff"])
- y_all: pd.DataFrame = ratios_per_sample[["sex", "ff"]]
+ x_all: npt.NDArray = ratios_per_sample.drop(columns=["sex", "ff"]).to_numpy()
+ y_all: npt.NDArray = ratios_per_sample[["sex", "ff"]].to_numpy()
# labels for regression (fetal fraction)
- y_ff_all = y_all["ff"]
+ y_ff_all = y_all[:, 1]
# labels for classification (sex)
- y_sex_all = y_all["sex"]
+ y_sex_all = y_all[:, 0]
- # Reduce dimensionality with PCA
- logging.info("Calculating Principal Components")
+ # Global PCA fit on all data for later use in ensemble model
+ logging.info("Fitting global PCA...")
global_pca = PCA(n_components=n_feat)
- x_all_pca = global_pca.fit_transform(x_all)
+ global_pca.fit(x_all)
params = {}
if tune:
# Enable hyperparameter tuning
logging.info("Tuning hyperparameters...")
if model == ModelOptions.NEURAL:
- params = neural_tune(x_all_pca, y_all.to_numpy(), out_dir)
+ params = neural_tune(x_all, y_all, n_feat, out_dir)
elif model == ModelOptions.XGBOOST:
- params = xgboost_tune(x_all_pca, y_all.to_numpy(), out_dir)
+ params = xgboost_tune(x_all, y_all, n_feat, out_dir)
# Set up training (k-fold cross-validation)
# Create directory to store fold metrics
@@ -197,12 +200,15 @@ def preface_train(
# Set up k-fold cross-validation
kf: KFold = KFold(n_splits=n_folds, shuffle=True, random_state=42)
- for fold, (train_idx, test_idx) in enumerate(kf.split(x_all_pca), 1):
+ for fold, (train_idx, test_idx) in enumerate(kf.split(x_all), 1):
logging.info(f"Processing Fold {fold}/{n_folds}...")
# split into train and test sets
- x_train, x_test = x_all_pca[train_idx], x_all_pca[test_idx]
- y_train, y_test = y_all.iloc[train_idx], y_all.iloc[test_idx]
+ # reduce dimensionality with PCA for each fold to prevent data leakage
+ training_pca = PCA(n_components=n_feat)
+ x_train_pca = training_pca.fit_transform(x_all[train_idx])
+ x_test_pca = training_pca.transform(x_all[test_idx])
+ y_train, y_test = y_all[train_idx], y_all[test_idx]
y_train_reg, y_test_reg = y_ff_all[train_idx], y_ff_all[test_idx]
y_train_class, y_test_class = y_sex_all[train_idx], y_sex_all[test_idx]
@@ -210,13 +216,12 @@ def preface_train(
logging.info(f"Training fold {fold}...")
if model == ModelOptions.NEURAL:
model, predictions = neural_fit(
- x_train,
- x_test,
- y_train_reg.to_numpy(),
- y_train_class.to_numpy(),
- y_test_reg.to_numpy(),
- y_test_class.to_numpy(),
- n_feat,
+ x_train_pca,
+ x_test_pca,
+ y_train_reg,
+ y_train_class,
+ y_test_reg,
+ y_test_class,
params,
)
# Save fold model
@@ -224,16 +229,17 @@ def preface_train(
elif model == ModelOptions.XGBOOST:
model, predictions = xgboost_fit(
- x_train, x_test, y_train.to_numpy(), y_test.to_numpy(), params
+ x_train_pca, x_test_pca, y_train, y_test, params
)
+ model.save_model(out_dir / "training_folds" / f"fold_{fold}.bin") # type: ignore
fold_models.append(model)
# Plot regression performance
reg_perf = plot_regression_performance(
predictions["regression_predictions"],
- y_test_reg.to_numpy(),
- global_pca.explained_variance_ratio_,
+ y_test_reg,
+ training_pca.explained_variance_ratio_,
n_feat,
"PREFACE (%)",
"FF (%)",
@@ -264,32 +270,31 @@ def preface_train(
fold_metrics_df = pd.DataFrame(fold_metrics)
fold_metrics_df.to_csv(out_dir / "training_fold_metrics.csv", index=False)
- # Build ensemble model from fold models
- logging.info("Building ensemble model from fold models...")
- ensemble_model = build_ensemble(len(x_all.columns), global_pca, fold_models)
- ensemble_model.save(out_dir / "PREFACE")
-
- # Final evaluation on all training data
- logging.info("Evaluating final model on all training data...")
- predictions = ensemble_model.predict(x_all)
- info_overall = plot_regression_performance(
- predictions[0].flatten(),
- y_ff_all.to_numpy(),
- global_pca.explained_variance_ratio_,
- n_feat,
- "PREFACE (%)",
- "FF (%)",
- out_dir / "overall_performance.png",
- )
-
- with open(out_dir / "training_statistics.txt", "w", encoding="utf-8") as f:
- f.write(
- f"""PREFACE - PREdict FetAl ComponEnt
- Training time: {time.time() - start_time:.0f} seconds
- Overall correlation (r): {info_overall["correlation"]:.4f}
- Overall mean absolute error (MAE): {info_overall["mae"]:.4f} ± {info_overall["sd_diff"]:.4f}
- """
- )
+ # # Build ensemble model from fold models
+ # logging.info("Building ensemble model from fold models...")
+ # ensemble_model = build_ensemble(global_pca, fold_models, x_all.shape[1], out_dir / "PREFACE.onnx")
+
+ # # Final evaluation on all training data
+ # logging.info("Evaluating final model on all training data...")
+ # predictions = ensemble_model.run()
+ # info_overall = plot_regression_performance(
+ # predictions[0][0][0].flatten(),
+ # y_ff_all,
+ # global_pca.explained_variance_ratio_,
+ # n_feat,
+ # "PREFACE (%)",
+ # "FF (%)",
+ # out_dir / "overall_performance.png",
+ # )
+
+ # with open(out_dir / "training_statistics.txt", "w", encoding="utf-8") as f:
+ # f.write(
+ # f"""PREFACE - PREdict FetAl ComponEnt
+ # Training time: {time.time() - start_time:.0f} seconds
+ # Overall correlation (r): {info_overall["correlation"]:.4f}
+ # Overall mean absolute error (MAE): {info_overall["mae"]:.4f} ± {info_overall["sd_diff"]:.4f}
+ # """
+ # )
logging.info(
f"Finished! Consult '{out_dir / 'training_statistics.txt'}' "
From ae47558012ef57043c80c1d73e98bf06e2c0f7e1 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 15:42:23 +0100
Subject: [PATCH 22/50] Add imputation methods
---
src/preface/train.py | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/src/preface/train.py b/src/preface/train.py
index bc74e5f..c2404c4 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -12,7 +12,7 @@
import sklearn
import numpy.typing as npt
from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
-from sklearn.impute import IterativeImputer
+from sklearn.impute import IterativeImputer, SimpleImputer, KNNImputer
from sklearn.decomposition import PCA
from sklearn.metrics import f1_score, mean_absolute_error, r2_score, roc_auc_score
from sklearn.model_selection import KFold
@@ -36,9 +36,11 @@ class ModelOptions(Enum):
XGBOOST = "xgboost"
-class ModeOptions(Enum):
- TRAIN = "train"
- TUNE = "tune"
+class ImputeOptions(Enum):
+ ZERO = "zero" # assume missing values are zero
+ MICE = "mice" # impute missing values using MICE
+ MEAN = "mean" # impute missing values by calculating mean
+ KNN = "knn" # impute missing values using k-nearest neighbors
def preface_train(
@@ -47,8 +49,8 @@ def preface_train(
),
out_dir: Path = typer.Option(os.getcwd(), "--outdir", help="Output directory"),
# Data handling
- impute: bool = typer.Option(
- False, "--impute", help="Impute missing values instead of assuming zero"
+ impute: ImputeOptions = typer.Option(
+ ImputeOptions.ZERO, "--impute", help="Impute missing values"
),
exclude_chrs: list[str] = typer.Option(
EXCLUDE_CHRS, "--exclude-chrs", help="Chromosomes to exclude from training"
@@ -144,7 +146,7 @@ def preface_train(
# we can either impute missing values with the mean ratio of that feature
# or assume zero (no change).
# Option 1: Impute NaN through MICE (Multiple Imputation by Chained Equations)
- if impute:
+ if impute == ImputeOptions.MICE:
# Check sklearn version for compatibility
sk_version = sklearn.__version__
if sk_version != "1.8.0":
@@ -166,10 +168,30 @@ def preface_train(
columns=ratios_per_sample.columns,
)
# Option 2: Assume missing values are zero (no change)
- else:
+ elif impute == ImputeOptions.ZERO:
logging.info("Assuming missing values are zero...")
ratios_per_sample = ratios_per_sample.fillna(0.0)
+ # Option 3: Impute missing values by calculating mean
+ elif impute == ImputeOptions.MEAN:
+ logging.info("Imputing missing values using mean strategy...")
+ imputer = SimpleImputer(strategy="mean")
+ ratios_per_sample = pd.DataFrame(
+ imputer.fit_transform(ratios_per_sample),
+ index=ratios_per_sample.index,
+ columns=ratios_per_sample.columns,
+ )
+
+ # Option 4: Impute missing values using k-nearest neighbors
+ elif impute == ImputeOptions.KNN:
+ logging.info("Imputing missing values using k-nearest neighbors...")
+ imputer = KNNImputer(n_neighbors=5)
+ ratios_per_sample = pd.DataFrame(
+ imputer.fit_transform(ratios_per_sample),
+ index=ratios_per_sample.index,
+ columns=ratios_per_sample.columns,
+ )
+
# Split into features and labels
x_all: npt.NDArray = ratios_per_sample.drop(columns=["sex", "ff"]).to_numpy()
y_all: npt.NDArray = ratios_per_sample[["sex", "ff"]].to_numpy()
From 5c39a1f1f1234166881e5f1081ba7c8799939b67 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 17:12:46 +0100
Subject: [PATCH 23/50] fixes
---
pixi.lock | 6 +++---
pyproject.toml | 2 +-
src/preface/train.py | 9 ++-------
3 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/pixi.lock b/pixi.lock
index 54415ae..80801ae 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -2386,16 +2386,16 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: a62ce1d73d0b5581dc96ae08f3ce585615d07cc5f48eb209b2e1c42a450cedab
+ sha256: e63025806c01506cd9b2f649aaf94e0bffedcbe45ea32df2b93ba4c359dc68e1
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
- scikit-learn==1.8.0
- tensorflow>=2.20.0,<3
- matplotlib>=3.10.8,<4
- - joblib>=1.5.3,<2
- statsmodels>=0.14.6,<0.15
- typer>=0.20.0,<0.21
+ - rich>=13.0.0,<15
- xgboost>=3.1.2,<4
- optuna>=4.6.0,<5
- optuna-integration[tfkeras]>=4.6.0,<5
@@ -2405,7 +2405,7 @@ packages:
- onnxmltools>=1.14.0,<2
- skl2onnx>=1.19.1,<2
- onnxconverter-common>=1.16.0,<2
- - onnxruntime
+ - onnxruntime>=1.23.2,<2
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
diff --git a/pyproject.toml b/pyproject.toml
index 3c03fa6..ae100b5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -17,9 +17,9 @@ dependencies = [
"scikit-learn==1.8.0",
"tensorflow>=2.20.0,<3",
"matplotlib>=3.10.8,<4",
- "joblib>=1.5.3,<2",
"statsmodels>=0.14.6,<0.15",
"typer>=0.20.0,<0.21",
+ "rich>=13.0.0,<15",
"xgboost>=3.1.2,<4",
"optuna>=4.6.0,<5",
"optuna-integration[tfkeras]>=4.6.0,<5",
diff --git a/src/preface/train.py b/src/preface/train.py
index c2404c4..6303d36 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -200,11 +200,6 @@ def preface_train(
# labels for classification (sex)
y_sex_all = y_all[:, 0]
- # Global PCA fit on all data for later use in ensemble model
- logging.info("Fitting global PCA...")
- global_pca = PCA(n_components=n_feat)
- global_pca.fit(x_all)
-
params = {}
if tune:
# Enable hyperparameter tuning
@@ -218,7 +213,7 @@ def preface_train(
# Create directory to store fold metrics
os.makedirs(out_dir / "training_folds", exist_ok=True)
fold_metrics = []
- fold_models: list[keras.Model] = []
+ fold_models: list[tuple[PCA, keras.Model]] = []
# Set up k-fold cross-validation
kf: KFold = KFold(n_splits=n_folds, shuffle=True, random_state=42)
@@ -255,7 +250,7 @@ def preface_train(
)
model.save_model(out_dir / "training_folds" / f"fold_{fold}.bin") # type: ignore
- fold_models.append(model)
+ fold_models.append((training_pca, model))
# Plot regression performance
reg_perf = plot_regression_performance(
From 13a32005eef0836473bea99176460c75ff157691 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 17:13:08 +0100
Subject: [PATCH 24/50] move imputation into CV loop
---
src/preface/lib/impute.py | 66 ++++++++++++++++++++++
src/preface/lib/neural.py | 14 +++--
src/preface/train.py | 114 +++++++++-----------------------------
3 files changed, 103 insertions(+), 91 deletions(-)
create mode 100644 src/preface/lib/impute.py
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
new file mode 100644
index 0000000..6bd6606
--- /dev/null
+++ b/src/preface/lib/impute.py
@@ -0,0 +1,66 @@
+import logging
+from enum import Enum
+
+import numpy as np
+import numpy.typing as npt
+import sklearn
+from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
+from sklearn.impute import IterativeImputer, KNNImputer, SimpleImputer
+
+
+class ImputeOptions(Enum):
+ ZERO = "zero" # assume missing values are zero
+ MICE = "mice" # impute missing values using MICE
+ MEAN = "mean" # impute missing values by calculating mean
+ MEDIAN = "median" # impute missing values by calculating median
+ KNN = "knn" # impute missing values using k-nearest neighbors
+
+
+def impute_nan(values: npt.NDArray, method: ImputeOptions) -> npt.NDArray:
+ """
+ Handle NaN values
+ Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
+ Here the input log2 ratios indicate relative coverage to a reference,
+ we can either impute missing values or assume zero (no change).
+ """
+ # Option 1: Impute NaN through MICE (Multiple Imputation by Chained Equations)
+ if method == ImputeOptions.MICE:
+ # Check sklearn version for compatibility
+ sk_version = sklearn.__version__
+ if sk_version != "1.8.0":
+ logging.warning(f"""PREFACE uses imputation and was developed using scikit-learn version 1.8.0.
+ Since imputation is still experimental, it may be subject to change in other versions.
+ You are using version {sk_version}. Proceed with caution.""")
+
+ logging.info("Imputing missing values using MICE... This might take a while.")
+ imputer = IterativeImputer(
+ random_state=42, max_iter=10, initial_strategy="mean"
+ )
+ imputed_values = imputer.fit_transform(values)
+
+
+ # Option 2: Assume missing values are zero (no change)
+ elif method == ImputeOptions.ZERO:
+ logging.info("Assuming missing values are zero...")
+ imputed_values = np.where(np.isnan(values), 0.0, values)
+
+ # Option 3: Impute missing values by calculating mean
+ elif method == ImputeOptions.MEAN:
+ logging.info("Imputing missing values using mean strategy...")
+ imputer = SimpleImputer(strategy="mean")
+ imputed_values = imputer.fit_transform(values)
+
+ # Option 4: Impute missing values by calculating mean
+ elif method == ImputeOptions.MEDIAN:
+ logging.info("Imputing missing values using median strategy...")
+ imputer = SimpleImputer(strategy="median")
+ imputed_values = imputer.fit_transform(values)
+
+ # Option 5: Impute missing values using k-nearest neighbors
+ elif method == ImputeOptions.KNN:
+ logging.info("Imputing missing values using k-nearest neighbors...")
+ imputer = KNNImputer(n_neighbors=5)
+ imputed_values = imputer.fit_transform(values)
+
+ return imputed_values
+
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 1fcf627..68859c1 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -92,10 +92,8 @@ def multi_output_nn(
def neural_fit(
x_train: npt.NDArray,
x_test: npt.NDArray,
- y_train_reg: npt.NDArray,
- y_train_class: npt.NDArray,
- y_test_reg: npt.NDArray,
- y_test_class: npt.NDArray,
+ y_train: npt.NDArray,
+ y_test: npt.NDArray,
params: dict,
) -> tuple[Model, dict]:
"""Build a multi-output neural network for regression and classification."""
@@ -107,6 +105,14 @@ def neural_fit(
"dropout_rate": 0.3,
}
+ # Split targets
+ # Assume y[:, 0] = class (sex), y[:, 1] = regression (ff)
+ # TODO: this is very brittle, make it more robust
+ y_train_reg: npt.NDArray = y_train[:, 1]
+ y_train_class: npt.NDArray = y_train[:, 0]
+ y_test_reg: npt.NDArray = y_test[:, 1]
+ y_test_class: npt.NDArray = y_test[:, 0]
+
# Early stopping callback
early_stop = keras.callbacks.EarlyStopping(
monitor="val_loss", patience=5, restore_best_weights=True
diff --git a/src/preface/train.py b/src/preface/train.py
index 6303d36..d3f2136 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -9,10 +9,7 @@
from enum import Enum
import pandas as pd
import typer
-import sklearn
import numpy.typing as npt
-from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
-from sklearn.impute import IterativeImputer, SimpleImputer, KNNImputer
from sklearn.decomposition import PCA
from sklearn.metrics import f1_score, mean_absolute_error, r2_score, roc_auc_score
from sklearn.model_selection import KFold
@@ -25,6 +22,7 @@
)
from preface.lib.xgboost import xgboost_tune, xgboost_fit
from preface.lib.neural import neural_tune, neural_fit
+from preface.lib.impute import ImputeOptions, impute_nan
# from preface.lib.ensemble import build_ensemble
# Constants
@@ -36,13 +34,6 @@ class ModelOptions(Enum):
XGBOOST = "xgboost"
-class ImputeOptions(Enum):
- ZERO = "zero" # assume missing values are zero
- MICE = "mice" # impute missing values using MICE
- MEAN = "mean" # impute missing values by calculating mean
- KNN = "knn" # impute missing values using k-nearest neighbors
-
-
def preface_train(
samplesheet: Path = typer.Option(
..., "--samplesheet", help="Path to samplesheet file"
@@ -140,74 +131,18 @@ def preface_train(
logging.info("Creating training frame...")
- # Handle NaN values
- # Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
- # Since the input log2 ratios indicate relative coverage to a reference,
- # we can either impute missing values with the mean ratio of that feature
- # or assume zero (no change).
- # Option 1: Impute NaN through MICE (Multiple Imputation by Chained Equations)
- if impute == ImputeOptions.MICE:
- # Check sklearn version for compatibility
- sk_version = sklearn.__version__
- if sk_version != "1.8.0":
- logging.warning(f"""PREFACE uses imputation and was developed using scikit-learn version 1.8.0.
- Since imputation is still experimental, it may be subject to change in other versions.
- You are using version {sk_version}. Proceed with caution.""")
-
- logging.info("Imputing missing values using MICE... This might take a while.")
- imputer = IterativeImputer(
- random_state=42, max_iter=10, initial_strategy="mean", verbose=2
- )
- logging.info("Fitting imputer to data...")
- training_df_array = imputer.fit_transform(ratios_per_sample)
- logging.info(f"Imputation completed. Sample of imputed data:\n{training_df_array[:10]}")
-
- ratios_per_sample = pd.DataFrame(
- training_df_array,
- index=ratios_per_sample.index,
- columns=ratios_per_sample.columns,
- )
- # Option 2: Assume missing values are zero (no change)
- elif impute == ImputeOptions.ZERO:
- logging.info("Assuming missing values are zero...")
- ratios_per_sample = ratios_per_sample.fillna(0.0)
-
- # Option 3: Impute missing values by calculating mean
- elif impute == ImputeOptions.MEAN:
- logging.info("Imputing missing values using mean strategy...")
- imputer = SimpleImputer(strategy="mean")
- ratios_per_sample = pd.DataFrame(
- imputer.fit_transform(ratios_per_sample),
- index=ratios_per_sample.index,
- columns=ratios_per_sample.columns,
- )
-
- # Option 4: Impute missing values using k-nearest neighbors
- elif impute == ImputeOptions.KNN:
- logging.info("Imputing missing values using k-nearest neighbors...")
- imputer = KNNImputer(n_neighbors=5)
- ratios_per_sample = pd.DataFrame(
- imputer.fit_transform(ratios_per_sample),
- index=ratios_per_sample.index,
- columns=ratios_per_sample.columns,
- )
-
# Split into features and labels
x_all: npt.NDArray = ratios_per_sample.drop(columns=["sex", "ff"]).to_numpy()
y_all: npt.NDArray = ratios_per_sample[["sex", "ff"]].to_numpy()
- # labels for regression (fetal fraction)
- y_ff_all = y_all[:, 1]
- # labels for classification (sex)
- y_sex_all = y_all[:, 0]
- params = {}
+ train_params = {}
if tune:
# Enable hyperparameter tuning
logging.info("Tuning hyperparameters...")
if model == ModelOptions.NEURAL:
- params = neural_tune(x_all, y_all, n_feat, out_dir)
+ train_params = neural_tune(x_all, y_all, n_feat, out_dir)
elif model == ModelOptions.XGBOOST:
- params = xgboost_tune(x_all, y_all, n_feat, out_dir)
+ train_params = xgboost_tune(x_all, y_all, n_feat, out_dir)
# Set up training (k-fold cross-validation)
# Create directory to store fold metrics
@@ -221,42 +156,47 @@ def preface_train(
logging.info(f"Processing Fold {fold}/{n_folds}...")
# split into train and test sets
- # reduce dimensionality with PCA for each fold to prevent data leakage
- training_pca = PCA(n_components=n_feat)
- x_train_pca = training_pca.fit_transform(x_all[train_idx])
- x_test_pca = training_pca.transform(x_all[test_idx])
+ x_train, x_test = x_all[train_idx], x_all[test_idx]
y_train, y_test = y_all[train_idx], y_all[test_idx]
- y_train_reg, y_test_reg = y_ff_all[train_idx], y_ff_all[test_idx]
- y_train_class, y_test_class = y_sex_all[train_idx], y_sex_all[test_idx]
+
+ y_test_class: npt.NDArray = y_test[:, 0]
+ y_test_reg: npt.NDArray = y_test[:, 1]
+
+ # impute data
+ x_train = impute_nan(x_train, impute)
+ x_test = impute_nan(x_test, impute)
+
+ # reduce dimensionality with PCA for each fold to prevent data leakage
+ fold_pca = PCA(n_components=n_feat)
+ x_train = fold_pca.fit_transform(x_train)
+ x_test = fold_pca.transform(x_test)
# Train
logging.info(f"Training fold {fold}...")
if model == ModelOptions.NEURAL:
model, predictions = neural_fit(
- x_train_pca,
- x_test_pca,
- y_train_reg,
- y_train_class,
- y_test_reg,
- y_test_class,
- params,
+ x_train,
+ x_test,
+ y_train,
+ y_test,
+ train_params,
)
# Save fold model
model.save(out_dir / "training_folds" / f"fold_{fold}.keras") # type: ignore
elif model == ModelOptions.XGBOOST:
model, predictions = xgboost_fit(
- x_train_pca, x_test_pca, y_train, y_test, params
+ x_train, x_test, y_train, y_test, train_params
)
model.save_model(out_dir / "training_folds" / f"fold_{fold}.bin") # type: ignore
- fold_models.append((training_pca, model))
+ fold_models.append((fold_pca, model))
# Plot regression performance
reg_perf = plot_regression_performance(
predictions["regression_predictions"],
y_test_reg,
- training_pca.explained_variance_ratio_,
+ fold_pca.explained_variance_ratio_,
n_feat,
"PREFACE (%)",
"FF (%)",
@@ -287,8 +227,8 @@ def preface_train(
fold_metrics_df = pd.DataFrame(fold_metrics)
fold_metrics_df.to_csv(out_dir / "training_fold_metrics.csv", index=False)
- # # Build ensemble model from fold models
- # logging.info("Building ensemble model from fold models...")
+ # Build ensemble model from fold models
+ logging.info("Building ensemble model from fold models...")
# ensemble_model = build_ensemble(global_pca, fold_models, x_all.shape[1], out_dir / "PREFACE.onnx")
# # Final evaluation on all training data
From aa94c4c999659d8d4fa3f2368ee4b92f6696b242 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 17:36:42 +0100
Subject: [PATCH 25/50] Drop R script
---
.dockerignore | 1 +
.gitignore | 1 +
PREFACE.R | 370 --------------------------------------------------
3 files changed, 2 insertions(+), 370 deletions(-)
delete mode 100755 PREFACE.R
diff --git a/.dockerignore b/.dockerignore
index ca28682..1200df8 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -6,6 +6,7 @@ __pycache__
*.pyc
*.pyo
*.pyd
+*.R
.DS_Store
data
examples
diff --git a/.gitignore b/.gitignore
index 2b8a5bd..3200a62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
.DS_Store
.Rhistory
+.R
data/
*.egg-info
__pycache__/
diff --git a/PREFACE.R b/PREFACE.R
deleted file mode 100755
index 4530a70..0000000
--- a/PREFACE.R
+++ /dev/null
@@ -1,370 +0,0 @@
-train <- function(args){
-
- start.time <- proc.time()
-
- # Additional lib
-
- suppressMessages(library('foreach'))
- suppressMessages(library('doParallel'))
- suppressMessages(library('MASS'))
- suppressMessages(library('irlba'))
-
- # Arg parse
-
- ## Mandatory
-
- man.args <- c('--config', '--outdir')
- if (length(which(man.args %in% args)) != length(man.args)) unrec.args('train')
- config.file = args[which(args == '--config') + 1]
- out.dir = args[which(args == '--outdir') + 1]
- if(!(file.exists(config.file))){
- cat(paste0('The file \'', config.file, '\' does not exist.\n'))
- quit(save = 'no')
- }
- args = args[args != config.file]
-
- dir.create(out.dir, showWarnings = FALSE, recursive = TRUE)
- if(!(file.exists(out.dir))){
- cat(paste0('Could not create directory \'', out.dir, '\'.\n'))
- quit(save = 'no')
- }
- args = args[args != out.dir]
-
- ## Optional
- op.args <- c('--nfeat', '--hidden', '--olm', '--femprop', '--noskewcorrect', '--cpus')
-
- n.feat <- parse.op.arg(args, '--nfeat', 50)[[1]] ; args <- parse.op.arg(args, '--nfeat', 50)[[2]]
- hidden <- parse.op.arg(args, '--hidden', 2)[[1]] ; args <- parse.op.arg(args, '--hidden', 2)[[2]]
- cpus <- parse.op.arg(args, '--cpus', 1)[[1]] ; args <- parse.op.arg(args, '--cpus', 1)[[2]]
- is.olm = F ; if ('--olm' %in% args) is.olm = T
- skewcorrect = T ; if ('--noskewcorrect' %in% args) skewcorrect = F
- train.gender = c('M') ; if ('--femprop' %in% args) train.gender = c('M', 'F')
-
- ## Others
-
- if(any(!(args %in% c(man.args, op.args)))){
- cat(paste0('Argument(s) \'', paste0(args[!(args %in% c(man.args, op.args))], collapse = '\', \''), '\' not recognized. Will ignore.\n'))
- }
-
- out.dir <- paste0(out.dir, '/')
-
- # Start training
-
- ## Load necessary files
-
- config.file <- read.csv(file = config.file, sep = '\t', header = T,
- comment.char='', colClasses = c('character', 'character', 'factor', 'numeric'))
- if (length(which(config.file$gender %in% train.gender)) < n.feat){
- cat(paste0('Please provide at least ', n.feat, ' labeled samples.\n'))
- quit(save = 'no')
- }
-
- config.file <- config.file[sample(nrow(config.file)),]
-
- training.frame <- read.table(config.file$filepath[1], header = T, sep = '\t')
- training.frame <- training.frame[,colnames(training.frame) %in% c('chr', 'start', 'end')]
- training.frame <- training.frame
-
- registerDoParallel(cpus)
- training.frame.sub <- foreach(i = 1:nrow(config.file), .combine = 'cbind') %dopar% {
- sample <- config.file$ID[i]
- cat(paste0('Loading sample ', sample, ' | ', nrow(config.file) - i, '/', nrow(config.file), ' remaining ...\n'))
- bin.table <- fread(config.file$filepath[i], header = T, sep = '\t')
- return(suppressWarnings(as.numeric(bin.table$ratio[bin.table$chr != 'Y'])))
- }
-
- colnames(training.frame.sub) <- config.file$ID
- X.ratios <- as.data.frame(training.frame.sub['X' == training.frame$chr, ])
- X.ratios <- 2 ** colMeans(X.ratios, na.rm = T)
-
- cat(paste0('Creating training frame ...\n'))
-
- training.frame <- cbind(training.frame[!(training.frame$chr %in% exclude.chrs),],
- training.frame.sub[!(training.frame$chr %in% exclude.chrs),])
- training.frame.t <- t(training.frame[4:ncol(training.frame)])
- colnames(training.frame.t) <- paste0(training.frame$chr, ':', training.frame$start, '-', training.frame$end)
-
- training.frame <- as.data.frame(training.frame.t)
- rm(training.frame.t)
-
- training.frame <- training.frame[,colSums(is.na(training.frame)) < nrow(config.file) * 0.01]
- possible.features <- colnames(training.frame)
- mean.features <- colMeans(training.frame, na.rm = T)
-
- na.index <- which(is.na(training.frame), arr.ind=TRUE)
- if (length(na.index[,2])) training.frame[na.index] <- mean.features[na.index[,2]]
-
- cat(paste0('Remaining training features after \'NA\' filtering: ', length(possible.features), '\n'))
-
- ## Predictive modeling
-
- dir.create(paste0(out.dir, 'training_repeats'), showWarnings = FALSE, recursive = TRUE)
-
- repeats = 10
- test.percentage = 1/repeats
-
- test.number = length(which(config.file$gender %in% train.gender)) * test.percentage
-
- max.feat <- length(which(config.file$gender %in% train.gender)) - as.integer(test.number) - 1
- if (n.feat > max.feat){
- cat(paste0('Too few samples were provided for --nfeat ', n.feat, ', using --nfeat ', max.feat, '\n'))
- n.feat <- max.feat
- }
-
- oper <- foreach(i = 1:repeats) %dopar% {
-
- cat(paste0('Model training | Repeat ', i,'/', repeats, ' ...\n'))
-
- test.index.overall <- which(config.file$gender %in% train.gender)[(as.integer((i-1)*test.number) + 1):as.integer(i*test.number)]
- train.index.overall <- sort(which(config.file$gender %in% train.gender)[!((which(config.file$gender %in% train.gender)) %in% test.index.overall)])
- train.index.subset <- sort(which(config.file$gender[-test.index.overall] %in% train.gender))
-
- cat(paste0('\tExecuting principal component analysis ...\n'))
- pca.train <- suppressWarnings(prcomp_irlba(training.frame[-test.index.overall,],
- n = min(n.feat * 10, nrow(training.frame[-test.index.overall,]) - 1), scale. = F))
-
- X.train <- as.matrix(pca.train$x[train.index.subset, ])
- Y.train <- as.matrix(config.file$FF[train.index.overall], ncol = 1)
- X.test <- as.matrix(scale(training.frame[test.index.overall,], pca.train$center, pca.train$scale) %*% pca.train$rotation)
- Y.test <- as.matrix(config.file$FF[test.index.overall], ncol = 1)
-
- if (is.olm){
- cat(paste0('\tTraining ordinary linear model ...\n'))
- model <- glmnet(x = X.train[,1:n.feat], y = Y.train, family='gaussian', lambda = 0)
- prediction = as.numeric(predict.glmnet(model, X.test[,1:n.feat]))
- } else {
- train.nn <- X.train[,1:n.feat]
- train.nn <- cbind(train.nn, Y.train)
- colnames(train.nn) <- c(colnames(train.nn)[1:(ncol(train.nn) - 1)], 'FF')
- f <- paste(colnames(X.train)[1:(ncol(train.nn) - 1)], collapse=' + ')
- f <- paste('FF ~',f)
- f <- as.formula(f)
- cat(paste0('\tTraining neural network ...\n'))
- model <- train.neural(f, train.nn, hidden)
- prediction = as.numeric(compute(model, X.test[,1:n.feat])$net.result)
- }
-
- info <- plot.performance(prediction, Y.test, summary(pca.train), n.feat, 'PREFACE (%)', 'FF (%)', paste0(out.dir, 'training_repeats/', 'repeat_', i,'.png'))
-
- results <- list()
- results$intercept <- as.numeric(info[1])
- results$slope <- as.numeric(info[2])
- results$prediction <- prediction
- return(results)
- }
- stopImplicitCluster()
-
- predictions <- c()
- for(rep in 1:repeats){
- predictions <- c(predictions, oper[[rep]]$prediction)
- }
-
- if (skewcorrect){
- p <- sample(length(predictions))[1:(length(predictions)/4)]
- fit <- coef(lsfit(predictions[p], config.file$FF[config.file$gender %in% train.gender][p]))
- the.intercept <- fit[1]
- the.slope <- fit[2]
- } else {
- the.intercept <- 0
- the.slope <- 1
- }
-
- ## FFX
-
- png(paste0(out.dir, 'FFX.png'), width=5, height=2.8, units='in', res=1024)
- par(mar=c(2.7,2,0,0.3), mgp=c(1.5, 0.2, 0.2), mfrow=c(1,2), xpd = NA, oma=c(0,1.5,0,0))
-
- v1 <- config.file$FF[config.file$gender == 'M']
- v2 <- X.ratios[config.file$gender == 'M']
- plot(v1, v2, pch = 16, cex = 0.4, axes = F, xlab = 'FF (%)', ylab = 'μ(ratio X)',
- xlim = c(0, max(v1)))
- fit <- rlm(v2 ~ v1)
-
- r2wls <- function(x){
- SSe <- sum(x$w*(x$resid)^2)
- observed <- x$resid+x$fitted
- SSt <- sum(x$w*(observed-weighted.mean(observed,x$w))^2)
- value <- 1-SSe/SSt;
- return(value);
- }
-
- r <- r2wls(fit) ** 0.5 ; fit <- coef(fit)
-
- par(xpd = F)
- segments(min(v1), fit[1] + min(v1) * fit[2], max(v1), fit[1] + max(v1) * fit[2], lwd = 3, lty = 2, c = color.A)
- par(xpd = NA)
-
- axis(1, tcl=0.5)
- axis(2, tcl=0.5, las = 2)
-
- legend('topright', legend = c('RLS fit', 'f(x)=x', paste0('(wr = ', signif(r, 4), ')')),
- bty = 'n', lty = c(2, 3, -1), col = c(color.A, color.B, 'black'), cex = 0.7, text.col = c(color.A, color.B, 'black'),
- text.font = c(2, 2, 1))
-
-
- v2 <- (v2 - fit[1]) / fit[2]
- plot(v1, v2, pch = 16, cex = 0.4, axes = F, xlab = 'FF (%)', ylab = 'FFX (%)',
- xlim = c(0, max(v1)))
- segments(min(v1), min(v1), max(v1), max(v1), lwd = 3, lty = 3, c = color.B)
-
-
- axis(1, tcl=0.5)
- axis(2, tcl=0.5, las = 2)
-
- dev.off()
-
- the.intercept.X <- fit[1]
- the.slope.X <- fit[2]
-
- ## Output final model & accuracy statistics
-
- predictions <- the.intercept + the.slope * predictions
-
- cat(paste0('Executing final principal component analysis ...\n'))
- pca.train <- suppressWarnings(prcomp_irlba(training.frame, n = min(n.feat * 10, nrow(training.frame) - 1), scale. = F))
- X.train <- as.matrix(pca.train$x[which(config.file$gender %in% train.gender), ])
- Y.train <- as.matrix(config.file$FF[which(config.file$gender %in% train.gender)], ncol = 1)
-
- if (is.olm){
- cat(paste0('Training final ordinary linear model ...\n'))
- model <- glmnet(x = X.train[,1:n.feat], y = Y.train, family='gaussian', lambda = 0)
- } else {
- train.nn <- X.train[,1:n.feat]
- train.nn <- cbind(train.nn, Y.train)
- colnames(train.nn) <- c(colnames(train.nn)[1:(ncol(train.nn) - 1)], 'FF')
- f <- paste(colnames(X.train)[1:(ncol(train.nn) - 1)], collapse=' + ')
- f <- paste('FF ~',f)
- f <- as.formula(f)
- cat(paste0('Training final neural network ...\n'))
- model <- train.neural(f, train.nn, hidden)
- }
-
- train.config.file <- config.file[config.file$gender %in% train.gender, ]
-
- info <- plot.performance(predictions, train.config.file$FF, summary(pca.train),
- n.feat, 'PREFACE (%)', 'FF (%)', paste0(out.dir, 'overall_performance.png'))
-
- index.10 <- which(train.config.file$FF < 20 - predictions)
- deviations.10 <- abs(predictions[index.10] - train.config.file$FF[index.10])
-
- deviations <- abs(predictions - train.config.file$FF)
- outliers.index <- which(deviations > info[4] + 3 * info[5])
- outliers <- train.config.file$ID[outliers.index]
- outlier.values <- deviations[outliers.index]
- outliers.values.noabs <- c(predictions - train.config.file$FF)[outliers.index]
-
- sink(paste0(out.dir, 'training_statistics.txt'))
- cat('PREFACE - PREdict FetAl ComponEnt\n\n')
- if (length(outliers) != 0){
- cat(paste0('Below, some of the top candidates for outlier removal are listed.\n',
- 'If you know some of these are low quality/have sex aberrations (when using FFY as response variable), remove them from the config file and re-run.\n',
- 'Avoid removing other cases, as this will result in inaccurate performance statistics and possible overfitting towards irrelevant models.\n\n'))
- cat('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n')
- cat('ID\tFF (%) - PREFACE (%)\n')
- for (i in rev(order(outlier.values))){
- cat(paste0(outliers[i], '\t', outliers.values.noabs[i], '\n'))
- }
- cat('_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n')
- }
- elapsed.time <- proc.time() - start.time
- cat(paste0('Training time: ', as.character(round(elapsed.time[3])), ' seconds\n'))
- cat(paste0('Overall correlation (r): ', info[5], '\n'))
- cat(paste0('Overall mean absolute error (MAE): ', info[3], ' ± ', info[4], '\n'))
- cat(paste0('FF < 10% mean absolute error (MAE): ', mean(deviations.10), ' ± ', sd(deviations.10), '\n'))
- cat(paste0('Correction for skew: \n'))
- cat(paste0('\tIntercept: ', the.intercept, '\n'))
- cat(paste0('\tSlope: ', the.slope, '\n\n'))
- cat(paste0('Do not forget to verify whether the \'--nfeat\' parameter captures the first \'random\' phase (and not too much of the \'non-random\' phase) at \'', out.dir, 'overall_performance.png\'.\n',
- 'If you believe this parameter is not located in an optimal position, decrease/increase \'--nfeat\' and re-run.'))
- sink()
-
- pca.center <- pca.train$center
- pca.scale <- pca.train$scale
- pca.rotation <- pca.train$rotation[,1:n.feat]
-
- if(is.olm){
- model <- model[which(names(model) %in% c('beta', 'lambda', 'a0', 'offset'))]
- } else {
- model <- model[which(names(model) %in% c('linear.output', 'weights', 'model.list'))]
- }
-
- save('n.feat', 'mean.features', 'possible.features', 'pca.center',
- 'pca.scale', 'pca.rotation', 'model', 'the.intercept',
- 'the.slope', 'the.intercept.X', 'the.slope.X', 'is.olm',
- file = paste0(out.dir, 'model.RData'))
-
- cat(paste0('Finished! Consult \'', out.dir, 'training_statistics.txt\' to analyse your model\'s performance.\n'))
-}
-
-predict <- function(args){
-
- # Arg parse
-
- man.args <- c('--infile', '--model')
- if (length(which(man.args %in% args)) != length(man.args)) unrec.args('predict')
- in.file = args[which(args == '--infile') + 1]
- model = args[which(args == '--model') + 1]
- if(!(file.exists(in.file))){
- cat(paste0('The file \'', in.file, '\' does not exist.\n'))
- quit(save = 'no')
- }
- if(!(file.exists(model))){
- cat(paste0('The file \'', model, '\' does not exist.\n'))
- quit(save = 'no')
- }
- args <- args[!(args %in% c(in.file, model))]
-
- op.args <- c('--json')
- if ('--json' %in% args){
- json = as.character(args[which(args == '--json') + 1])
- if (!is.na(json)){
- args = args[args != json]
- }
- } else {
- json = ''
- }
-
- if(any(!(args %in% c(man.args, op.args, in.file, model)))){
- cat(paste0('Argument(s) \'', paste0(args[!(args %in% c(man.args, op.args))], collapse = '\', \''), '\' not recognized. Will ignore.\n'))
- }
-
- # Predict
-
- load(model)
- model$act.fct <- function (x) {1/(1 + exp(-x))}
- bin.table <- fread(in.file, header = T, sep = '\t')
- feat.id <- paste0(bin.table$chr, ':', bin.table$start, '-', bin.table$end)
- X.ratio <- 2 ** mean(as.numeric(bin.table$ratio['X' == bin.table$chr]), na.rm = T)
- ratio <- as.numeric(bin.table$ratio[which(feat.id %in% possible.features)])
-
- FFX <- (X.ratio - the.intercept.X) / the.slope.X
-
- if (any(is.na(ratio))){
- ratio[is.na(ratio)] <- mean.features[is.na(ratio)]
- }
-
- projected.ratio <- as.matrix(scale(t(ratio), pca.center, pca.scale) %*% pca.rotation)
- if (is.olm){
- prediction <- as.numeric(predict.glmnet(model, projected.ratio))
- } else{
- prediction = as.numeric(compute(model, projected.ratio)$net.result)
- }
-
- prediction <- the.intercept + the.slope * prediction
-
- json.dict <- paste0('{\"FFX\": ', FFX / 100, ', \"PREFACE\": ', prediction / 100, '}')
-
- if (is.na(json)){
- cat(json.dict)
- cat('\n')
- } else {
- if (json == ''){
- cat(paste0('FFX = ', signif(FFX, 4), '%\n'))
- cat(paste0('PREFACE = ', signif(prediction, 4), '%\n'))
- } else {
- sink(paste0(json))
- cat(json.dict)
- sink()
- }
- }
-}
From 6788fbc56c74d6fed9d04f4fda75863aa3b622bb Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 17:36:56 +0100
Subject: [PATCH 26/50] set default loglevel to INFO
---
src/preface/preface.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/preface/preface.py b/src/preface/preface.py
index 60b5d43..732a2cf 100644
--- a/src/preface/preface.py
+++ b/src/preface/preface.py
@@ -23,7 +23,7 @@
# Configure logging
logging.basicConfig(
- level="NOTSET",
+ level="INFO",
format="%(message)s",
datefmt="[%X]",
handlers=[RichHandler(rich_tracebacks=True, tracebacks_suppress=[typer])],
From cd669a6d2470ca03669b298e4aa75bc1f439a8e7 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 17:37:44 +0100
Subject: [PATCH 27/50] move imputation into CV loop for tune
---
src/preface/lib/impute.py | 1 -
src/preface/lib/neural.py | 27 +++++++++++++++++----------
src/preface/lib/xgboost.py | 20 +++++++++++++++-----
src/preface/train.py | 6 ++----
4 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index 6bd6606..086eb4b 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -38,7 +38,6 @@ def impute_nan(values: npt.NDArray, method: ImputeOptions) -> npt.NDArray:
)
imputed_values = imputer.fit_transform(values)
-
# Option 2: Assume missing values are zero (no change)
elif method == ImputeOptions.ZERO:
logging.info("Assuming missing values are zero...")
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 68859c1..925127a 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -10,9 +10,10 @@
Model,
layers,
)
+from preface.lib.impute import ImputeOptions, impute_nan
-def neural_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path) -> dict:
+def neural_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path, impute_option: ImputeOptions) -> dict:
def objective(trial) -> float:
params = {
"n_layers": trial.suggest_int("n_layers", 1, 3),
@@ -26,27 +27,34 @@ def objective(trial) -> float:
scores = []
for t_idx, v_idx in kf_internal.split(features):
+ x_train, x_val = features[t_idx], features[v_idx]
+ y_train, y_val = targets[t_idx], targets[v_idx]
+
+ # impute missing values
+ x_train = impute_nan(x_train, impute_option)
+ x_val = impute_nan(x_val, impute_option)
+
# reduce dimensionality with PCA
pca = PCA(n_components=n_components)
- features_pca = pca.fit_transform(features)
+ x_train = pca.fit_transform(x_train)
+ x_val = pca.transform(x_val)
model = multi_output_nn(
- input_dim=features_pca.shape[1],
+ input_dim=x_train.shape[1],
n_layers=params["n_layers"],
hidden_size=params["hidden_size"],
learning_rate=params["learning_rate"],
dropout_rate=params["dropout_rate"],
)
history = model.fit(
- features[t_idx],
- targets[t_idx],
- validation_data=(features[v_idx], targets[v_idx]),
+ x_train,
+ y_train,
+ validation_data=(x_val, y_val),
epochs=50,
batch_size=16,
callbacks=[
optuna.integration.TFKerasPruningCallback(trial, "val_loss")
- ],
- verbose=True
+ ]
)
scores.append(min((history.history["val_loss"])))
@@ -131,8 +139,7 @@ def neural_fit(
),
epochs=100,
batch_size=32,
- verbose=True,
- callbacks=[early_stop],
+ callbacks=[early_stop]
)
# Evaluate
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index b15cdd0..5fd193b 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -10,8 +10,10 @@
from xgboost import XGBRegressor
from sklearn.decomposition import PCA
+from preface.lib.impute import impute_nan, ImputeOptions
-def xgboost_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path) -> dict:
+
+def xgboost_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path, impute_option: ImputeOptions) -> dict:
def objective(trial) -> float:
params = {
# number of boosting rounds
@@ -33,15 +35,23 @@ def objective(trial) -> float:
scores = []
for t_idx, v_idx in kf_internal.split(features):
+ x_train, x_val = features[t_idx], features[v_idx]
+ y_train, y_val = targets[t_idx], targets[v_idx]
+
+ # impute missing values
+ x_train = impute_nan(x_train, impute_option)
+ x_val = impute_nan(x_val, impute_option)
+
# Reduce dimensionality with PCA
pca = PCA(n_components=n_components)
- features_pca = pca.fit_transform(features)
+ x_train = pca.fit_transform(x_train)
+ x_val = pca.transform(x_val)
# Train and evaluate model
model = XGBRegressor(**params)
- model.fit(features_pca[t_idx], targets[t_idx])
- preds = model.predict(features_pca[v_idx])
- scores.append(mean_squared_error(targets[v_idx], preds))
+ model.fit(x_train, y_train)
+ preds = model.predict(x_val)
+ scores.append(mean_squared_error(y_val, preds))
return np.mean(scores).astype(float)
study = optuna.create_study(direction="minimize")
diff --git a/src/preface/train.py b/src/preface/train.py
index d3f2136..28ccf4c 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -139,10 +139,8 @@ def preface_train(
if tune:
# Enable hyperparameter tuning
logging.info("Tuning hyperparameters...")
- if model == ModelOptions.NEURAL:
- train_params = neural_tune(x_all, y_all, n_feat, out_dir)
- elif model == ModelOptions.XGBOOST:
- train_params = xgboost_tune(x_all, y_all, n_feat, out_dir)
+ tuner = neural_tune if model == ModelOptions.NEURAL else xgboost_tune
+ train_params = tuner(x_all, y_all, n_feat, out_dir, impute)
# Set up training (k-fold cross-validation)
# Create directory to store fold metrics
From 8c7dfc35d163af222afd049f9002653ff8816b8e Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 17:50:39 +0100
Subject: [PATCH 28/50] tmp commit
---
src/preface/lib/ensemble.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
index 7977c23..e2aa5e2 100644
--- a/src/preface/lib/ensemble.py
+++ b/src/preface/lib/ensemble.py
@@ -12,7 +12,7 @@
def build_ensemble(
- pca_obj: PCA, models: list[Model | XGBRegressor], input_dim: int, output_path: Path
+ models: list[tuple[PCA, Model | XGBRegressor]], input_dim: int, output_path: Path
) -> tuple[ModelProto | GraphProto | FunctionProto]:
"""
Save an ensemble of models (either Keras NNs or XGBoost regressors) combined with a PCA
@@ -23,8 +23,11 @@ def build_ensemble(
pca_out_name = pca_onnx.graph.output[0].name # type: ignore
prefixed_models = []
- model_type = "nn" if isinstance(models[0], Model) else "xgb"
for i, m in enumerate(models):
+ pca = m[0]
+ model = m[1]
+ model_type = "nn" if isinstance(models[0], Model) else "xgb"
+
if model_type == "nn":
m_onnx = onnxmltools.convert_keras(m, name=f"fold_{i}")
elif model_type == "xgb":
From 3004aa5e4d158878884728f4b7905e3c1959fb88 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 18:51:57 +0100
Subject: [PATCH 29/50] bugfixes
---
pixi.lock | 16 ++-
pyproject.toml | 1 +
src/preface/lib/ensemble.py | 261 ++++++++++++++++++++++++++++-------
src/preface/lib/functions.py | 41 +++++-
src/preface/lib/impute.py | 14 +-
src/preface/lib/neural.py | 9 +-
src/preface/lib/xgboost.py | 4 +-
src/preface/predict.py | 96 ++++++-------
src/preface/train.py | 101 +++++++++-----
9 files changed, 396 insertions(+), 147 deletions(-)
diff --git a/pixi.lock b/pixi.lock
index 80801ae..8f636f8 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -120,6 +120,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
@@ -241,6 +242,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
@@ -355,6 +357,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
@@ -2386,7 +2389,7 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: e63025806c01506cd9b2f649aaf94e0bffedcbe45ea32df2b93ba4c359dc68e1
+ sha256: e5ff08eeff805ec836b603be3c4da0890fbaf8fba8e660de5d0e3b28eb217abe
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -2406,6 +2409,7 @@ packages:
- skl2onnx>=1.19.1,<2
- onnxconverter-common>=1.16.0,<2
- onnxruntime>=1.23.2,<2
+ - tf2onnx
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
@@ -3428,6 +3432,16 @@ packages:
- pytest ; extra == 'tests'
- pytest-cov ; extra == 'tests'
requires_python: '>=3.10'
+- pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
+ name: tf2onnx
+ version: 1.8.4
+ sha256: 1ebabb96c914da76e23222b6107a8b248a024bf259d77f027e6690099512d457
+ requires_dist:
+ - numpy>=1.14.1
+ - onnx>=1.4.1
+ - requests
+ - six
+ - flatbuffers
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
name: threadpoolctl
version: 3.6.0
diff --git a/pyproject.toml b/pyproject.toml
index ae100b5..6a50b2e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,6 +30,7 @@ dependencies = [
"skl2onnx>=1.19.1,<2",
"onnxconverter-common>=1.16.0,<2",
"onnxruntime>=1.23.2,<2",
+ "tf2onnx>=1.8.4,<2",
]
[build-system]
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
index e2aa5e2..956fdf1 100644
--- a/src/preface/lib/ensemble.py
+++ b/src/preface/lib/ensemble.py
@@ -2,74 +2,228 @@
import onnx
import onnxmltools
-from onnx import TensorProto, ModelProto, GraphProto, FunctionProto, helper
+from onnx import TensorProto, helper
from onnx.compose import add_prefix, merge_models
from skl2onnx import convert_sklearn
-from skl2onnx.common.data_types import FloatTensorType
+from skl2onnx.common.data_types import FloatTensorType, Int64TensorType
from sklearn.decomposition import PCA
from tensorflow.keras import Model # type: ignore
from xgboost import XGBRegressor
-
+import numpy as np
def build_ensemble(
- models: list[tuple[PCA, Model | XGBRegressor]], input_dim: int, output_path: Path
-) -> tuple[ModelProto | GraphProto | FunctionProto]:
+ models: list[tuple[object, PCA, Model | XGBRegressor]],
+ input_dim: int,
+ output_path: Path,
+ metadata: dict[str, str] | None = None
+) -> None:
"""
- Save an ensemble of models (either Keras NNs or XGBoost regressors) combined with a PCA
+ Save an ensemble of models (Imputer + PCA + Model) combined.
+ models: List of (Imputer, PCA, Model) tuples.
+ metadata: Optional dictionary of metadata to save in the ONNX model.
"""
+
+ prefixed_models = []
+
+ # Process each fold
+ for i, (imputer, pca, model) in enumerate(models):
+ fold_prefix = f"fold_{i}_"
+
+ # 1. Convert Imputer (if exists)
+ # Input to Imputer is FloatTensorType([None, input_dim])
+ initial_type = [("input", FloatTensorType([None, input_dim]))]
+
+ if imputer is not None:
+ # simple imputer
+ imp_onnx = convert_sklearn(imputer, initial_types=initial_type, target_opset=12)
+ # Rename output of imputer to match input of PCA
+ # But wait, we can just chain them via merge_models later?
+ # Easier to chain them linearly first or merge step by step.
+ current_model = imp_onnx
+ # The output name of sklearn models is typically "variable" or similar.
+ # We need to find the output name.
+ imp_out_name = current_model.graph.output[0].name
+ else:
+ # No imputer (ZERO strategy). We need a "Identity" or just pass input.
+ # However, if we want to fill NaNs with 0, we might need a custom ONNX node or assume input has 0s.
+ # For now, let's assume the user handles NaN -> 0 before or use Identity.
+ # Actually, `convert_sklearn` handles NaN?
+ # If the user selected ZERO, they expect NaNs to be 0.
+ # We can create a simple graph that takes input and returns input (Identity),
+ # relying on the caller to provide 0s or ONNX runtime to handle it.
+ # BETTER: create a dummy identity model.
+
+ # For simplicity in this fix, we assume input is already clean if imputer is None,
+ # OR we rely on the fact that we can't easily inject "FillNaN(0)" without complex node creation.
+ # Let's start with the PCA conversion using the initial type.
+ current_model = None
+ imp_out_name = "input"
- initial_type = [("input", FloatTensorType([None, input_dim]))]
- pca_onnx = convert_sklearn(pca_obj, initial_types=initial_type, target_opset=12)
- pca_out_name = pca_onnx.graph.output[0].name # type: ignore
+ # 2. Convert PCA
+ # Input to PCA is the output of Imputer (or "input")
+ if current_model:
+ # If we have an imputer model, the PCA input type should match its output
+ # But convert_sklearn needs `initial_types`.
+ # We can convert PCA independently with same shape.
+ pca_initial_type = [("input_pca", FloatTensorType([None, input_dim]))]
+ else:
+ pca_initial_type = initial_type
+
+ pca_onnx = convert_sklearn(pca, initial_types=pca_initial_type, target_opset=12)
+ pca_in_name = pca_onnx.graph.input[0].name
+ pca_out_name = pca_onnx.graph.output[0].name
+
+ if current_model:
+ # Merge Imputer + PCA
+ current_model = merge_models(
+ current_model,
+ pca_onnx,
+ io_map=[(imp_out_name, pca_in_name)]
+ )
+ # Update output name
+ current_out_name = pca_out_name
+ else:
+ current_model = pca_onnx
+ current_out_name = pca_out_name
+ # If we had no imputer, we need to rename the input to "input" to standardize
+ # actually pca_onnx input is "input" (from initial_type) or "input_pca".
+ # We will handle renaming at the global merge.
- prefixed_models = []
- for i, m in enumerate(models):
- pca = m[0]
- model = m[1]
- model_type = "nn" if isinstance(models[0], Model) else "xgb"
+ # 3. Convert Model
+ # Input to Model is PCA output. Shape: [None, n_components]
+ n_comps = pca.n_components_
+
+ model_type = "nn" if isinstance(model, Model) else "xgb"
if model_type == "nn":
- m_onnx = onnxmltools.convert_keras(m, name=f"fold_{i}")
- elif model_type == "xgb":
+ # tf2onnx / onnxmltools
+ # Keras conversion doesn't need initial_types usually, it reads from model
+ m_onnx = onnxmltools.convert_keras(model, name=f"fold_{i}_model", target_opset=12)
+ else:
+ # XGBoost
m_onnx = onnxmltools.convert_xgboost(
- m,
- initial_types=[
- (pca_out_name, FloatTensorType([None, pca_obj.n_components_]))
- ],
+ model,
+ initial_types=[("input_model", FloatTensorType([None, n_comps]))],
+ target_opset=12
)
- else:
- raise ValueError("Model must be either Keras Model or XGBRegressor")
-
- # Prefixing prevents node name collisions between the 10 folds
- prefixed_models.append(add_prefix(m_onnx, prefix=f"fold_{i}_"))
+
+ m_in_name = m_onnx.graph.input[0].name
+
+ # Merge (Imputer+PCA) + Model
+ current_model = merge_models(
+ current_model,
+ m_onnx,
+ io_map=[(current_out_name, m_in_name)]
+ )
+
+ # Prefix everything in this fold's graph
+ prefixed_model = add_prefix(current_model, prefix=fold_prefix)
+ prefixed_models.append(prefixed_model)
- # --- 2. Merge Graphs ---
- combined_model = pca_onnx
- for i in range(len(prefixed_models)):
+ # --- Merge All Folds ---
+ # We want a single input "input" that feeds into all fold_i_input
+
+ # Start with the first fold
+ combined_model = prefixed_models[0]
+
+ # Identify the input name of the first fold
+ # It should be "fold_0_input" (if we used "input" name initially)
+ # logic: add_prefix adds prefix to all names.
+ # The input of the chain was "input" (or "input_pca").
+ # So it becomes "fold_0_input".
+
+ for i in range(1, len(prefixed_models)):
combined_model = merge_models(
- combined_model, # type: ignore
+ combined_model,
prefixed_models[i],
- io_map=[(pca_out_name, f"fold_{i}_{pca_out_name}")],
+ # No connection between folds
)
+
+ graph = combined_model.graph
+
+ # Now we need to broadcast the global "input" to "fold_0_input", "fold_1_input", ...
+ # We create a new input "global_input" and Identity nodes or just rewire?
+ # Rewiring is safer.
+
+ # Find all inputs that look like "fold_X_input" or "fold_X_input_pca"
+ fold_inputs = []
+ for node in graph.input:
+ if node.name.endswith("input") or node.name.endswith("input_pca"):
+ fold_inputs.append(node.name)
+
+ # Create a global input
+ global_input_name = "input"
+ # remove existing inputs from graph.input (they become internal nodes fed by global input)
+ # Actually, we can just rename them? No, they are distinct nodes in the graph now?
+ # If we map them to the same tensor, they get connected.
+
+ # Let's add an Identity node for each fold input, fed by global_input
+ # Or simpler: create the global input, and add Split? Or just use same name?
+ # In ONNX, if multiple nodes use "input", it's valid.
+
+ # So we want to replace all usages of "fold_i_input" with "global_input".
+ for node in graph.node:
+ for idx, input_name in enumerate(node.input):
+ if input_name in fold_inputs:
+ node.input[idx] = global_input_name
+
+ # Reset graph inputs
+ while len(graph.input) > 0:
+ graph.input.pop()
+
+ graph.input.extend([helper.make_tensor_value_info(global_input_name, FloatTensorType([None, input_dim]).to_onnx_type().tensor_type.elem_type, [None, input_dim])])
- graph = combined_model.graph # type: ignore
-
- # --- 3. Identify Output Names for Averaging ---
- # For NN: Keras usually names outputs after the final layer (e.g., 'reg_out', 'class_out')
- # For XGB: Multi-output trees usually output a single tensor that we must split
- if model_type == "nn":
- reg_names = [f"fold_{i}_reg_output" for i in range(len(models))]
- class_names = [f"fold_{i}_class_output" for i in range(len(models))]
- else:
- # XGB strategy: We split the combined output tensor [Batch, 2] into two
- reg_names, class_names = [], []
- for i in range(len(models)):
- reg_node_out = f"fold_{i}_reg_split"
- class_node_out = f"fold_{i}_class_split"
- reg_names.append(reg_node_out)
- class_names.append(class_node_out)
+ # --- Average Outputs ---
+ # Identify outputs.
+ # NN: fold_i_reg_output, fold_i_class_output
+ # XGB: fold_i_variable (output of regressor) -> need to split?
+
+ # Note: earlier XGB code said it outputs [Batch, 2] for multi-output.
+ # We need to find the output names of the fold graphs.
+
+ reg_names = []
+ class_names = []
+
+ # Helper to find output names
+ for i, (_, _, model) in enumerate(models):
+ model_type = "nn" if isinstance(model, Model) else "xgb"
+ prefix = f"fold_{i}_"
+
+ if model_type == "nn":
+ # Keras outputs are typically named by layer names.
+ # In neural.py: "reg_output", "class_output"
+ reg_names.append(prefix + "reg_output")
+ class_names.append(prefix + "class_output")
+ else:
+ # XGBoost multi-output
+ # The output name from onnxmltools for XGB is usually "variable"
+ xgb_out = prefix + "variable"
+
+ # We need to split this output. It is [Batch, 2].
+ # Column 0: Reg, Column 1: Class (Prob)
+
+ # Add Split node
+ split_reg = f"{prefix}reg_split"
+ split_class = f"{prefix}class_split"
+
+ # Create Split node
+ # Attributes: axis=1, split=[1,1]
+ # Output: [split_reg, split_class]
+
+ split_node = helper.make_node(
+ "Split",
+ inputs=[xgb_out],
+ outputs=[split_reg, split_class],
+ name=f"{prefix}Split",
+ axis=1,
+ split=[1, 1]
+ )
+ graph.node.append(split_node)
+
+ reg_names.append(split_reg)
+ class_names.append(split_class)
- # --- 4. Add Mean Nodes for both heads ---
+ # Add Mean nodes
final_reg_name = "final_ff_score"
final_class_name = "final_sex_prob"
@@ -82,7 +236,7 @@ def build_ensemble(
graph.node.extend([mean_reg_node, mean_class_node])
- # --- 5. Clean up and finalize outputs ---
+ # Clean outputs
while len(graph.output) > 0:
graph.output.pop()
@@ -95,7 +249,12 @@ def build_ensemble(
]
)
- onnx.save(combined_model, output_path) # type: ignore
- print(f"Dual-head ensemble saved to {output_path}")
+ # Add metadata
+ if metadata:
+ for key, value in metadata.items():
+ meta = combined_model.metadata_props.add()
+ meta.key = key
+ meta.value = value
- return combined_model # type: ignore
+ onnx.save(combined_model, output_path)
+ print(f"Ensemble saved to {output_path}")
\ No newline at end of file
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index e1f96eb..6286a39 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -5,7 +5,7 @@
import pandas as pd
import statsmodels.api as sm
from sklearn.linear_model import LinearRegression
-from sklearn.metrics import mean_absolute_error
+from sklearn.metrics import mean_absolute_error, roc_curve, auc, confusion_matrix, ConfusionMatrixDisplay
COLOR_A: str = "#8DD1C6"
@@ -181,8 +181,41 @@ def plot_regression_performance(
}
-def plot_classification_performance():
- pass
+def plot_classification_performance(
+ y_prob: np.ndarray,
+ y_true: np.ndarray,
+ path: Path,
+) -> None:
+ """
+ Plot classification performance (ROC and Confusion Matrix).
+ """
+ _, axes = plt.subplots(1, 2, figsize=(10, 5))
+
+ # ROC Curve
+ ax = axes[0]
+ fpr, tpr, _ = roc_curve(y_true, y_prob)
+ roc_auc = auc(fpr, tpr)
+
+ ax.plot(fpr, tpr, color=COLOR_A, lw=2, label=f"ROC curve (area = {roc_auc:.2f})")
+ ax.plot([0, 1], [0, 1], color=COLOR_B, lw=2, linestyle="--")
+ ax.set_xlim([0.0, 1.0])
+ ax.set_ylim([0.0, 1.05])
+ ax.set_xlabel("False Positive Rate")
+ ax.set_ylabel("True Positive Rate")
+ ax.set_title("Receiver Operating Characteristic")
+ ax.legend(loc="lower right")
+
+ # Confusion Matrix
+ ax = axes[1]
+ y_pred = (y_prob >= 0.5).astype(int)
+ cm = confusion_matrix(y_true, y_pred)
+ disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=["Female", "Male"])
+ disp.plot(ax=ax, cmap="Blues", colorbar=False)
+ ax.set_title("Confusion Matrix")
+
+ plt.tight_layout()
+ plt.savefig(path, dpi=300)
+ plt.close()
def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
@@ -247,4 +280,4 @@ def plot_ffx(
)
plt.tight_layout()
plt.savefig(out_dir_path / "FFX.png", dpi=300)
- plt.close()
+ plt.close()
\ No newline at end of file
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index 086eb4b..28061f8 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -16,13 +16,19 @@ class ImputeOptions(Enum):
KNN = "knn" # impute missing values using k-nearest neighbors
-def impute_nan(values: npt.NDArray, method: ImputeOptions) -> npt.NDArray:
+def impute_nan(values: npt.NDArray, method: ImputeOptions) -> tuple[npt.NDArray, object]:
"""
Handle NaN values
Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
Here the input log2 ratios indicate relative coverage to a reference,
we can either impute missing values or assume zero (no change).
+
+ Returns:
+ tuple: (imputed_values, fitted_imputer)
+ Note: For ImputeOptions.ZERO, the fitted_imputer is None (handled manually).
"""
+ imputer = None
+
# Option 1: Impute NaN through MICE (Multiple Imputation by Chained Equations)
if method == ImputeOptions.MICE:
# Check sklearn version for compatibility
@@ -42,6 +48,8 @@ def impute_nan(values: npt.NDArray, method: ImputeOptions) -> npt.NDArray:
elif method == ImputeOptions.ZERO:
logging.info("Assuming missing values are zero...")
imputed_values = np.where(np.isnan(values), 0.0, values)
+ # For ZERO, we don't have a sklearn imputer, but we can simulate one or handle it in export
+ imputer = None
# Option 3: Impute missing values by calculating mean
elif method == ImputeOptions.MEAN:
@@ -49,7 +57,7 @@ def impute_nan(values: npt.NDArray, method: ImputeOptions) -> npt.NDArray:
imputer = SimpleImputer(strategy="mean")
imputed_values = imputer.fit_transform(values)
- # Option 4: Impute missing values by calculating mean
+ # Option 4: Impute missing values by calculating median
elif method == ImputeOptions.MEDIAN:
logging.info("Imputing missing values using median strategy...")
imputer = SimpleImputer(strategy="median")
@@ -61,5 +69,5 @@ def impute_nan(values: npt.NDArray, method: ImputeOptions) -> npt.NDArray:
imputer = KNNImputer(n_neighbors=5)
imputed_values = imputer.fit_transform(values)
- return imputed_values
+ return imputed_values, imputer
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 925127a..eb4a153 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -31,8 +31,8 @@ def objective(trial) -> float:
y_train, y_val = targets[t_idx], targets[v_idx]
# impute missing values
- x_train = impute_nan(x_train, impute_option)
- x_val = impute_nan(x_val, impute_option)
+ x_train, _ = impute_nan(x_train, impute_option)
+ x_val, _ = impute_nan(x_val, impute_option)
# reduce dimensionality with PCA
pca = PCA(n_components=n_components)
@@ -77,7 +77,8 @@ def multi_output_nn(
learning_rate: float,
dropout_rate: float,
) -> Model:
- x = layers.Input(shape=(input_dim,))
+ input_layer = layers.Input(shape=(input_dim,))
+ x = input_layer
for i in range(n_layers):
x = layers.Dense(hidden_size // (2 ** i), activation="relu")(x)
x = layers.Dropout(dropout_rate)(x)
@@ -87,7 +88,7 @@ def multi_output_nn(
# Head 2: Classification
class_out = layers.Dense(1, activation="sigmoid", name="class_output")(x)
- nn = Model(inputs=x, outputs=[reg_out, class_out])
+ nn = Model(inputs=input_layer, outputs=[reg_out, class_out])
nn.compile(
optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 5fd193b..708a598 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -39,8 +39,8 @@ def objective(trial) -> float:
y_train, y_val = targets[t_idx], targets[v_idx]
# impute missing values
- x_train = impute_nan(x_train, impute_option)
- x_val = impute_nan(x_val, impute_option)
+ x_train, _ = impute_nan(x_train, impute_option)
+ x_val, _ = impute_nan(x_val, impute_option)
# Reduce dimensionality with PCA
pca = PCA(n_components=n_components)
diff --git a/src/preface/predict.py b/src/preface/predict.py
index db9ba94..1427ca2 100644
--- a/src/preface/predict.py
+++ b/src/preface/predict.py
@@ -8,6 +8,7 @@
from rich import print
from pathlib import Path
import onnxruntime as ort
+import numpy as np
def preface_predict(
@@ -20,57 +21,58 @@ def preface_predict(
# Load model
preface_model: ort.InferenceSession = ort.InferenceSession(model_path)
+
+ # Check metadata for excluded chromosomes
+ meta = preface_model.get_modelmeta()
+ custom_props = meta.custom_metadata_map
+
+ if "exclude_chrs" in custom_props:
+ exclude_str = custom_props["exclude_chrs"]
+ if exclude_str:
+ exclude_chrs = exclude_str.split(",")
+ else:
+ exclude_chrs = []
+ print(f"[dim]Using excluded chromosomes from model metadata: {exclude_chrs}[/dim]")
+
ratios: pd.DataFrame = pd.read_csv(infile, sep="\t")
# Preprocess ratios
- preprocessed_ratios = preprocess_ratios(ratios, exclude_chrs=[])
-
- # x_bins = ratios[ratios["chr"] == "X"]
- # x_ratio: float
- # if len(x_bins) > 0:
- # x_ratio = float(2 ** np.mean(x_bins["ratio"].dropna()))
- # else:
- # x_ratio = float(np.nan)
-
- results = preface_model.run(None, {preface_model.get_inputs()[0].name: preprocessed_ratios.values})
- ff_score = results[0][0][0] # type: ignore
- sex_prob = results[1][0][0] # type: ignore
+ preprocessed_ratios = preprocess_ratios(ratios, exclude_chrs=exclude_chrs)
+
+ # Convert to float32
+ input_data = preprocessed_ratios.values.astype(np.float32)
+
+ # Run inference
+ # We can rely on position 0, 1 or names.
+ # build_ensemble saves: final_ff_score, final_sex_prob
+
+ # Get output names
+ output_names = [o.name for o in preface_model.get_outputs()]
+
+ # Run
+ results = preface_model.run(output_names, {preface_model.get_inputs()[0].name: input_data})
+
+ # Map results to meaningful variables
+ # If standard PREFACE model, names are specific.
+ # If unknown model, fallback to index.
+
+ ff_score = None
+ sex_prob = None
+
+ result_map = dict(zip(output_names, results))
+
+ if "final_ff_score" in result_map:
+ ff_score = result_map["final_ff_score"][0][0]
+ elif len(results) > 0:
+ ff_score = results[0][0][0]
+
+ if "final_sex_prob" in result_map:
+ sex_prob = result_map["final_sex_prob"][0][0]
+ elif len(results) > 1:
+ sex_prob = results[1][0][0]
+
sex_class = "Male" if sex_prob > 0.5 else "Female"
print("--- Patient Report ---")
print(f"Predicted FF Score: {ff_score:.4f}")
- print(f"Sex Probability: {sex_prob:.4f} ({sex_class})")
-
- # ffx: float = (x_ratio - intercept_x) / slope_x
-
- # bin_table["feat_id"] = (
- # bin_table["chr"].astype(str)
- # + ":"
- # + bin_table["start"].astype(str)
- # + "-"
- # + bin_table["end"].astype(str)
- # )
-
- # ratio_map = bin_table.set_index("feat_id")["ratio"]
- # features = ratio_map.reindex(possible_features)
- # features = features.fillna(mean_features)
-
- # features_array = features.values.reshape(1, -1)
-
- # projected_ratio = pca.transform(features_array)[:, :n_feat]
-
- # prediction = float(model.predict(projected_ratio).flatten()[0])
-
- # prediction = the_intercept + the_slope * prediction
-
- # json_dict = {"FFX": ffx / 100, "PREFACE": prediction / 100}
-
- # if json_output:
- # if json_output not in ("stdout", ""):
- # with open(json_output, "w", encoding="utf-8") as f:
- # json.dump(json_dict, f)
- # else:
- # print(json.dumps(json_dict))
- # else:
- # print(f"FFX = {ffx:.4g}%")
- # print(f"PREFACE = {prediction:.4g}%")
+ print(f"Sex Probability: {sex_prob:.4f} ({sex_class})")
\ No newline at end of file
diff --git a/src/preface/train.py b/src/preface/train.py
index 28ccf4c..ff9f6f5 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -3,13 +3,15 @@
"""
import os
-# import time
+import time
from pathlib import Path
import logging
from enum import Enum
import pandas as pd
import typer
+import numpy as np
import numpy.typing as npt
+import onnxruntime as ort
from sklearn.decomposition import PCA
from sklearn.metrics import f1_score, mean_absolute_error, r2_score, roc_auc_score
from sklearn.model_selection import KFold
@@ -23,7 +25,7 @@
from preface.lib.xgboost import xgboost_tune, xgboost_fit
from preface.lib.neural import neural_tune, neural_fit
from preface.lib.impute import ImputeOptions, impute_nan
-# from preface.lib.ensemble import build_ensemble
+from preface.lib.ensemble import build_ensemble
# Constants
EXCLUDE_CHRS: list[str] = ["13", "18", "21", "X", "Y"]
@@ -59,14 +61,14 @@ def preface_train(
False, "--tune", help="Enable automatic hyperparameter tuning"
),
# Model options
- model: ModelOptions = typer.Option(
+ model_type: ModelOptions = typer.Option(
ModelOptions.NEURAL, "--model", help="Type of model to train"
),
) -> None:
"""
Train and optionally tune the PREFACE model.
"""
- # start_time: float = time.time()
+ start_time: float = time.time()
# Load samplesheet
samplesheet_data: pd.DataFrame = pd.read_csv(
@@ -139,14 +141,14 @@ def preface_train(
if tune:
# Enable hyperparameter tuning
logging.info("Tuning hyperparameters...")
- tuner = neural_tune if model == ModelOptions.NEURAL else xgboost_tune
+ tuner = neural_tune if model_type == ModelOptions.NEURAL else xgboost_tune
train_params = tuner(x_all, y_all, n_feat, out_dir, impute)
# Set up training (k-fold cross-validation)
# Create directory to store fold metrics
os.makedirs(out_dir / "training_folds", exist_ok=True)
fold_metrics = []
- fold_models: list[tuple[PCA, keras.Model]] = []
+ fold_models: list[tuple[object, PCA, keras.Model]] = []
# Set up k-fold cross-validation
kf: KFold = KFold(n_splits=n_folds, shuffle=True, random_state=42)
@@ -161,8 +163,8 @@ def preface_train(
y_test_reg: npt.NDArray = y_test[:, 1]
# impute data
- x_train = impute_nan(x_train, impute)
- x_test = impute_nan(x_test, impute)
+ x_train, imputer = impute_nan(x_train, impute)
+ x_test, _ = impute_nan(x_test, impute)
# reduce dimensionality with PCA for each fold to prevent data leakage
fold_pca = PCA(n_components=n_feat)
@@ -171,7 +173,7 @@ def preface_train(
# Train
logging.info(f"Training fold {fold}...")
- if model == ModelOptions.NEURAL:
+ if model_type == ModelOptions.NEURAL:
model, predictions = neural_fit(
x_train,
x_test,
@@ -182,13 +184,13 @@ def preface_train(
# Save fold model
model.save(out_dir / "training_folds" / f"fold_{fold}.keras") # type: ignore
- elif model == ModelOptions.XGBOOST:
+ elif model_type == ModelOptions.XGBOOST:
model, predictions = xgboost_fit(
x_train, x_test, y_train, y_test, train_params
)
model.save_model(out_dir / "training_folds" / f"fold_{fold}.bin") # type: ignore
- fold_models.append((fold_pca, model))
+ fold_models.append((imputer, fold_pca, model))
# Plot regression performance
reg_perf = plot_regression_performance(
@@ -202,7 +204,11 @@ def preface_train(
)
# Plot classification performance
- plot_classification_performance()
+ plot_classification_performance(
+ predictions["class_probabilities"],
+ y_test_class,
+ out_dir / "training_folds" / f"fold_{fold}_classification.png",
+ )
# return metrics
metrics: dict = {
@@ -227,29 +233,54 @@ def preface_train(
# Build ensemble model from fold models
logging.info("Building ensemble model from fold models...")
- # ensemble_model = build_ensemble(global_pca, fold_models, x_all.shape[1], out_dir / "PREFACE.onnx")
-
- # # Final evaluation on all training data
- # logging.info("Evaluating final model on all training data...")
- # predictions = ensemble_model.run()
- # info_overall = plot_regression_performance(
- # predictions[0][0][0].flatten(),
- # y_ff_all,
- # global_pca.explained_variance_ratio_,
- # n_feat,
- # "PREFACE (%)",
- # "FF (%)",
- # out_dir / "overall_performance.png",
- # )
-
- # with open(out_dir / "training_statistics.txt", "w", encoding="utf-8") as f:
- # f.write(
- # f"""PREFACE - PREdict FetAl ComponEnt
- # Training time: {time.time() - start_time:.0f} seconds
- # Overall correlation (r): {info_overall["correlation"]:.4f}
- # Overall mean absolute error (MAE): {info_overall["mae"]:.4f} ± {info_overall["sd_diff"]:.4f}
- # """
- # )
+ build_ensemble(
+ fold_models,
+ x_all.shape[1],
+ out_dir / "PREFACE.onnx",
+ metadata={"exclude_chrs": ",".join(exclude_chrs)}
+ )
+
+ # Final evaluation on all training data
+ logging.info("Evaluating final model on all training data...")
+
+ # Load ONNX model
+ sess = ort.InferenceSession(out_dir / "PREFACE.onnx")
+ input_name = sess.get_inputs()[0].name
+
+ # Handle NaNs for evaluation if ZERO strategy was used (since ONNX graph might expect clean input for that case)
+ if impute == ImputeOptions.ZERO:
+ x_all_eval = np.nan_to_num(x_all, nan=0.0)
+ else:
+ x_all_eval = x_all
+
+ x_all_eval = x_all_eval.astype(np.float32)
+
+ predictions = sess.run(None, {input_name: x_all_eval})
+ y_ff_pred = predictions[0].flatten()
+
+ y_ff_all = y_all[:, 1]
+
+ # Use first fold's PCA for visualization
+ first_pca = fold_models[0][1]
+
+ info_overall = plot_regression_performance(
+ y_ff_pred,
+ y_ff_all,
+ first_pca.explained_variance_ratio_,
+ n_feat,
+ "PREFACE (%)",
+ "FF (%)",
+ out_dir / "overall_performance.png",
+ )
+
+ with open(out_dir / "training_statistics.txt", "w", encoding="utf-8") as f:
+ f.write(
+ f"""PREFACE - PREdict FetAl ComponEnt
+ Training time: {time.time() - start_time:.0f} seconds
+ Overall correlation (r): {info_overall["correlation"]:.4f}
+ Overall mean absolute error (MAE): {info_overall["mae"]:.4f} ± {info_overall["sd_diff"]:.4f}
+ """
+ )
logging.info(
f"Finished! Consult '{out_dir / 'training_statistics.txt'}' "
From 4906160c1ef4f400d0288e93e948459aafa7d25a Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 19:04:53 +0100
Subject: [PATCH 30/50] fix(ensemble): use tf2onnx with input signature for
keras models to prevent saving error
---
pixi.lock | 4 ++--
src/preface/lib/ensemble.py | 8 ++++++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/pixi.lock b/pixi.lock
index 8f636f8..2476d9b 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -2389,7 +2389,7 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: e5ff08eeff805ec836b603be3c4da0890fbaf8fba8e660de5d0e3b28eb217abe
+ sha256: e632e6e4efa31c951cd37a74b4b3f7d908e7094a73f2fa4658dde0dddf336846
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.3.5,<3
@@ -2409,7 +2409,7 @@ packages:
- skl2onnx>=1.19.1,<2
- onnxconverter-common>=1.16.0,<2
- onnxruntime>=1.23.2,<2
- - tf2onnx
+ - tf2onnx>=1.8.4,<2
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
index 956fdf1..b28900f 100644
--- a/src/preface/lib/ensemble.py
+++ b/src/preface/lib/ensemble.py
@@ -2,6 +2,8 @@
import onnx
import onnxmltools
+import tensorflow as tf
+import tf2onnx
from onnx import TensorProto, helper
from onnx.compose import add_prefix, merge_models
from skl2onnx import convert_sklearn
@@ -97,8 +99,10 @@ def build_ensemble(
if model_type == "nn":
# tf2onnx / onnxmltools
- # Keras conversion doesn't need initial_types usually, it reads from model
- m_onnx = onnxmltools.convert_keras(model, name=f"fold_{i}_model", target_opset=12)
+ # We explicitly provide input signature to avoid "ValueError: from_keras requires input_signature"
+ spec = (tf.TensorSpec((None, n_comps), tf.float32, name="input_model"),)
+ m_onnx, _ = tf2onnx.convert.from_keras(model, input_signature=spec, opset=12)
+ m_onnx.graph.name = f"fold_{i}_model"
else:
# XGBoost
m_onnx = onnxmltools.convert_xgboost(
From 7ac10ea57d808960ab79e22b12949146a7378233 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 19:49:27 +0100
Subject: [PATCH 31/50] formatting
---
src/preface/lib/ensemble.py | 138 +++++++++++++++++++++--------------
src/preface/lib/functions.py | 22 ++++--
src/preface/lib/impute.py | 19 ++---
src/preface/lib/neural.py | 35 ++++++---
src/preface/lib/xgboost.py | 8 +-
src/preface/predict.py | 34 +++++----
src/preface/train.py | 20 ++---
7 files changed, 170 insertions(+), 106 deletions(-)
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
index b28900f..625c7b1 100644
--- a/src/preface/lib/ensemble.py
+++ b/src/preface/lib/ensemble.py
@@ -7,54 +7,69 @@
from onnx import TensorProto, helper
from onnx.compose import add_prefix, merge_models
from skl2onnx import convert_sklearn
-from skl2onnx.common.data_types import FloatTensorType, Int64TensorType
+from skl2onnx.common.data_types import FloatTensorType
from sklearn.decomposition import PCA
from tensorflow.keras import Model # type: ignore
from xgboost import XGBRegressor
-import numpy as np
+
+
+def _ensure_opset(model_proto, version=12):
+ """
+ Force the default domain opset to a specific version.
+ skl2onnx sometimes produces older opsets (e.g. 9) even when 12 is requested.
+ """
+ for op in model_proto.opset_import:
+ if (not op.domain or op.domain == "ai.onnx") and op.version < version:
+ op.version = version
+ return model_proto
+
def build_ensemble(
- models: list[tuple[object, PCA, Model | XGBRegressor]],
- input_dim: int,
+ models: list[tuple[object, PCA, Model | XGBRegressor]],
+ input_dim: int,
output_path: Path,
- metadata: dict[str, str] | None = None
+ metadata: dict[str, str] | None = None,
) -> None:
"""
Save an ensemble of models (Imputer + PCA + Model) combined.
models: List of (Imputer, PCA, Model) tuples.
metadata: Optional dictionary of metadata to save in the ONNX model.
"""
-
+
prefixed_models = []
-
+
# Process each fold
for i, (imputer, pca, model) in enumerate(models):
fold_prefix = f"fold_{i}_"
-
+
# 1. Convert Imputer (if exists)
# Input to Imputer is FloatTensorType([None, input_dim])
initial_type = [("input", FloatTensorType([None, input_dim]))]
-
+
if imputer is not None:
# simple imputer
- imp_onnx = convert_sklearn(imputer, initial_types=initial_type, target_opset=12)
+ imp_onnx = convert_sklearn(
+ imputer, initial_types=initial_type, target_opset=12
+ )
+ _ensure_opset(imp_onnx, 12)
+
# Rename output of imputer to match input of PCA
- # But wait, we can just chain them via merge_models later?
+ # But wait, we can just chain them via merge_models later?
# Easier to chain them linearly first or merge step by step.
current_model = imp_onnx
# The output name of sklearn models is typically "variable" or similar.
# We need to find the output name.
- imp_out_name = current_model.graph.output[0].name
+ imp_out_name = current_model.graph.output[0].name # type: ignore
else:
# No imputer (ZERO strategy). We need a "Identity" or just pass input.
# However, if we want to fill NaNs with 0, we might need a custom ONNX node or assume input has 0s.
# For now, let's assume the user handles NaN -> 0 before or use Identity.
- # Actually, `convert_sklearn` handles NaN?
- # If the user selected ZERO, they expect NaNs to be 0.
- # We can create a simple graph that takes input and returns input (Identity),
+ # Actually, `convert_sklearn` handles NaN?
+ # If the user selected ZERO, they expect NaNs to be 0.
+ # We can create a simple graph that takes input and returns input (Identity),
# relying on the caller to provide 0s or ONNX runtime to handle it.
# BETTER: create a dummy identity model.
-
+
# For simplicity in this fix, we assume input is already clean if imputer is None,
# OR we rely on the fact that we can't easily inject "FillNaN(0)" without complex node creation.
# Let's start with the PCA conversion using the initial type.
@@ -69,18 +84,19 @@ def build_ensemble(
# We can convert PCA independently with same shape.
pca_initial_type = [("input_pca", FloatTensorType([None, input_dim]))]
else:
- pca_initial_type = initial_type
-
+ pca_initial_type = initial_type
+
pca_onnx = convert_sklearn(pca, initial_types=pca_initial_type, target_opset=12)
- pca_in_name = pca_onnx.graph.input[0].name
- pca_out_name = pca_onnx.graph.output[0].name
-
+ _ensure_opset(pca_onnx, 12)
+ pca_in_name = pca_onnx.graph.input[0].name # type: ignore
+ pca_out_name = pca_onnx.graph.output[0].name # type: ignore
+
if current_model:
# Merge Imputer + PCA
current_model = merge_models(
current_model,
pca_onnx,
- io_map=[(imp_out_name, pca_in_name)]
+ io_map=[(imp_out_name, pca_in_name)], # type: ignore
)
# Update output name
current_out_name = pca_out_name
@@ -94,105 +110,115 @@ def build_ensemble(
# 3. Convert Model
# Input to Model is PCA output. Shape: [None, n_components]
n_comps = pca.n_components_
-
+
model_type = "nn" if isinstance(model, Model) else "xgb"
-
+
if model_type == "nn":
# tf2onnx / onnxmltools
# We explicitly provide input signature to avoid "ValueError: from_keras requires input_signature"
- spec = (tf.TensorSpec((None, n_comps), tf.float32, name="input_model"),)
- m_onnx, _ = tf2onnx.convert.from_keras(model, input_signature=spec, opset=12)
+ spec = (tf.TensorSpec((None, n_comps), tf.float32, name="input_model"),) # type: ignore
+ m_onnx, _ = tf2onnx.convert.from_keras(
+ model, input_signature=spec, opset=12
+ )
m_onnx.graph.name = f"fold_{i}_model"
else:
# XGBoost
m_onnx = onnxmltools.convert_xgboost(
model,
initial_types=[("input_model", FloatTensorType([None, n_comps]))],
- target_opset=12
+ target_opset=12,
)
-
+
m_in_name = m_onnx.graph.input[0].name
-
+
# Merge (Imputer+PCA) + Model
current_model = merge_models(
current_model,
m_onnx,
- io_map=[(current_out_name, m_in_name)]
+ io_map=[(current_out_name, m_in_name)], # type: ignore
)
-
+
# Prefix everything in this fold's graph
prefixed_model = add_prefix(current_model, prefix=fold_prefix)
prefixed_models.append(prefixed_model)
# --- Merge All Folds ---
# We want a single input "input" that feeds into all fold_i_input
-
+
# Start with the first fold
combined_model = prefixed_models[0]
-
+
# Identify the input name of the first fold
# It should be "fold_0_input" (if we used "input" name initially)
# logic: add_prefix adds prefix to all names.
# The input of the chain was "input" (or "input_pca").
# So it becomes "fold_0_input".
-
+
for i in range(1, len(prefixed_models)):
combined_model = merge_models(
combined_model,
prefixed_models[i],
- # No connection between folds
+ io_map=[],
)
-
+
graph = combined_model.graph
-
+
# Now we need to broadcast the global "input" to "fold_0_input", "fold_1_input", ...
# We create a new input "global_input" and Identity nodes or just rewire?
# Rewiring is safer.
-
+
# Find all inputs that look like "fold_X_input" or "fold_X_input_pca"
fold_inputs = []
for node in graph.input:
if node.name.endswith("input") or node.name.endswith("input_pca"):
fold_inputs.append(node.name)
-
+
# Create a global input
global_input_name = "input"
# remove existing inputs from graph.input (they become internal nodes fed by global input)
# Actually, we can just rename them? No, they are distinct nodes in the graph now?
# If we map them to the same tensor, they get connected.
-
+
# Let's add an Identity node for each fold input, fed by global_input
# Or simpler: create the global input, and add Split? Or just use same name?
# In ONNX, if multiple nodes use "input", it's valid.
-
+
# So we want to replace all usages of "fold_i_input" with "global_input".
for node in graph.node:
for idx, input_name in enumerate(node.input):
if input_name in fold_inputs:
node.input[idx] = global_input_name
-
+
# Reset graph inputs
while len(graph.input) > 0:
graph.input.pop()
-
- graph.input.extend([helper.make_tensor_value_info(global_input_name, FloatTensorType([None, input_dim]).to_onnx_type().tensor_type.elem_type, [None, input_dim])])
+
+ graph.input.extend(
+ [
+ helper.make_tensor_value_info(
+ global_input_name,
+ FloatTensorType([None, input_dim]).to_onnx_type().tensor_type.elem_type,
+ [None, input_dim],
+ )
+ ]
+ )
# --- Average Outputs ---
- # Identify outputs.
+ # Identify outputs.
# NN: fold_i_reg_output, fold_i_class_output
# XGB: fold_i_variable (output of regressor) -> need to split?
-
+
# Note: earlier XGB code said it outputs [Batch, 2] for multi-output.
# We need to find the output names of the fold graphs.
-
+
reg_names = []
class_names = []
-
+
# Helper to find output names
for i, (_, _, model) in enumerate(models):
model_type = "nn" if isinstance(model, Model) else "xgb"
prefix = f"fold_{i}_"
-
+
if model_type == "nn":
# Keras outputs are typically named by layer names.
# In neural.py: "reg_output", "class_output"
@@ -202,28 +228,28 @@ def build_ensemble(
# XGBoost multi-output
# The output name from onnxmltools for XGB is usually "variable"
xgb_out = prefix + "variable"
-
+
# We need to split this output. It is [Batch, 2].
# Column 0: Reg, Column 1: Class (Prob)
-
+
# Add Split node
split_reg = f"{prefix}reg_split"
split_class = f"{prefix}class_split"
-
+
# Create Split node
# Attributes: axis=1, split=[1,1]
# Output: [split_reg, split_class]
-
+
split_node = helper.make_node(
"Split",
inputs=[xgb_out],
outputs=[split_reg, split_class],
name=f"{prefix}Split",
axis=1,
- split=[1, 1]
+ split=[1, 1],
)
graph.node.append(split_node)
-
+
reg_names.append(split_reg)
class_names.append(split_class)
@@ -261,4 +287,4 @@ def build_ensemble(
meta.value = value
onnx.save(combined_model, output_path)
- print(f"Ensemble saved to {output_path}")
\ No newline at end of file
+ print(f"Ensemble saved to {output_path}")
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index 6286a39..ede795d 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -5,7 +5,13 @@
import pandas as pd
import statsmodels.api as sm
from sklearn.linear_model import LinearRegression
-from sklearn.metrics import mean_absolute_error, roc_curve, auc, confusion_matrix, ConfusionMatrixDisplay
+from sklearn.metrics import (
+ mean_absolute_error,
+ roc_curve,
+ auc,
+ confusion_matrix,
+ ConfusionMatrixDisplay,
+)
COLOR_A: str = "#8DD1C6"
@@ -190,12 +196,12 @@ def plot_classification_performance(
Plot classification performance (ROC and Confusion Matrix).
"""
_, axes = plt.subplots(1, 2, figsize=(10, 5))
-
+
# ROC Curve
ax = axes[0]
fpr, tpr, _ = roc_curve(y_true, y_prob)
roc_auc = auc(fpr, tpr)
-
+
ax.plot(fpr, tpr, color=COLOR_A, lw=2, label=f"ROC curve (area = {roc_auc:.2f})")
ax.plot([0, 1], [0, 1], color=COLOR_B, lw=2, linestyle="--")
ax.set_xlim([0.0, 1.0])
@@ -204,15 +210,17 @@ def plot_classification_performance(
ax.set_ylabel("True Positive Rate")
ax.set_title("Receiver Operating Characteristic")
ax.legend(loc="lower right")
-
+
# Confusion Matrix
ax = axes[1]
y_pred = (y_prob >= 0.5).astype(int)
cm = confusion_matrix(y_true, y_pred)
- disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=["Female", "Male"])
+ disp = ConfusionMatrixDisplay(
+ confusion_matrix=cm, display_labels=["Female", "Male"]
+ )
disp.plot(ax=ax, cmap="Blues", colorbar=False)
ax.set_title("Confusion Matrix")
-
+
plt.tight_layout()
plt.savefig(path, dpi=300)
plt.close()
@@ -280,4 +288,4 @@ def plot_ffx(
)
plt.tight_layout()
plt.savefig(out_dir_path / "FFX.png", dpi=300)
- plt.close()
\ No newline at end of file
+ plt.close()
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index 28061f8..0ff57fa 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -9,26 +9,28 @@
class ImputeOptions(Enum):
- ZERO = "zero" # assume missing values are zero
- MICE = "mice" # impute missing values using MICE
- MEAN = "mean" # impute missing values by calculating mean
+ ZERO = "zero" # assume missing values are zero
+ MICE = "mice" # impute missing values using MICE
+ MEAN = "mean" # impute missing values by calculating mean
MEDIAN = "median" # impute missing values by calculating median
- KNN = "knn" # impute missing values using k-nearest neighbors
+ KNN = "knn" # impute missing values using k-nearest neighbors
-def impute_nan(values: npt.NDArray, method: ImputeOptions) -> tuple[npt.NDArray, object]:
+def impute_nan(
+ values: npt.NDArray, method: ImputeOptions
+) -> tuple[npt.NDArray, object]:
"""
Handle NaN values
Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
Here the input log2 ratios indicate relative coverage to a reference,
we can either impute missing values or assume zero (no change).
-
+
Returns:
tuple: (imputed_values, fitted_imputer)
Note: For ImputeOptions.ZERO, the fitted_imputer is None (handled manually).
"""
imputer = None
-
+
# Option 1: Impute NaN through MICE (Multiple Imputation by Chained Equations)
if method == ImputeOptions.MICE:
# Check sklearn version for compatibility
@@ -49,7 +51,7 @@ def impute_nan(values: npt.NDArray, method: ImputeOptions) -> tuple[npt.NDArray,
logging.info("Assuming missing values are zero...")
imputed_values = np.where(np.isnan(values), 0.0, values)
# For ZERO, we don't have a sklearn imputer, but we can simulate one or handle it in export
- imputer = None
+ imputer = None
# Option 3: Impute missing values by calculating mean
elif method == ImputeOptions.MEAN:
@@ -70,4 +72,3 @@ def impute_nan(values: npt.NDArray, method: ImputeOptions) -> tuple[npt.NDArray,
imputed_values = imputer.fit_transform(values)
return imputed_values, imputer
-
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index eb4a153..3a2b790 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -13,13 +13,21 @@
from preface.lib.impute import ImputeOptions, impute_nan
-def neural_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path, impute_option: ImputeOptions) -> dict:
+def neural_tune(
+ features: npt.NDArray,
+ targets: npt.NDArray,
+ n_components: int,
+ outdir: Path,
+ impute_option: ImputeOptions,
+) -> dict:
def objective(trial) -> float:
params = {
"n_layers": trial.suggest_int("n_layers", 1, 3),
"hidden_size": trial.suggest_int("hidden_size", 16, 128, step=16),
"learning_rate": trial.suggest_float("learning_rate", 1e-4, 1e-2, log=True),
"dropout_rate": trial.suggest_float("dropout_rate", 0.1, 0.5, step=0.1),
+ "epochs": trial.suggest_int("epochs", 20, 100, step=10),
+ "batch_size": trial.suggest_int("batch_size", 8, 64, step=8),
}
# Internal split for the tuner
@@ -27,6 +35,9 @@ def objective(trial) -> float:
scores = []
for t_idx, v_idx in kf_internal.split(features):
+ # Clear session to prevent "tf.function retracing" warning
+ keras.backend.clear_session()
+
x_train, x_val = features[t_idx], features[v_idx]
y_train, y_val = targets[t_idx], targets[v_idx]
@@ -50,8 +61,8 @@ def objective(trial) -> float:
x_train,
y_train,
validation_data=(x_val, y_val),
- epochs=50,
- batch_size=16,
+ epochs=params["epochs"],
+ batch_size=params["batch_size"],
callbacks=[
optuna.integration.TFKerasPruningCallback(trial, "val_loss")
]
@@ -80,7 +91,7 @@ def multi_output_nn(
input_layer = layers.Input(shape=(input_dim,))
x = input_layer
for i in range(n_layers):
- x = layers.Dense(hidden_size // (2 ** i), activation="relu")(x)
+ x = layers.Dense(hidden_size // (2**i), activation="relu")(x) # type: ignore
x = layers.Dropout(dropout_rate)(x)
# Head 1: Regression
@@ -106,6 +117,9 @@ def neural_fit(
params: dict,
) -> tuple[Model, dict]:
"""Build a multi-output neural network for regression and classification."""
+ # Clear session to prevent "tf.function retracing" warning
+ keras.backend.clear_session()
+
# default parameters
nn_default_params = {
"n_layers": 3,
@@ -113,7 +127,8 @@ def neural_fit(
"learning_rate": 1e-3,
"dropout_rate": 0.3,
}
-
+ epochs = params.pop("epochs", 50)
+ batch_size = params.pop("batch_size", 32)
# Split targets
# Assume y[:, 0] = class (sex), y[:, 1] = regression (ff)
# TODO: this is very brittle, make it more robust
@@ -128,7 +143,9 @@ def neural_fit(
)
# Create model
- model = multi_output_nn(input_dim=x_train.shape[1], **{**nn_default_params, **params})
+ model = multi_output_nn(
+ input_dim=x_train.shape[1], **{**nn_default_params, **params}
+ )
# Fit model
model.fit(
@@ -138,9 +155,9 @@ def neural_fit(
x_test,
{"reg_output": y_test_reg, "class_output": y_test_class},
),
- epochs=100,
- batch_size=32,
- callbacks=[early_stop]
+ epochs=epochs,
+ batch_size=batch_size,
+ callbacks=[early_stop],
)
# Evaluate
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 708a598..6308dbb 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -13,7 +13,13 @@
from preface.lib.impute import impute_nan, ImputeOptions
-def xgboost_tune(features: npt.NDArray, targets: npt.NDArray, n_components: int, outdir: Path, impute_option: ImputeOptions) -> dict:
+def xgboost_tune(
+ features: npt.NDArray,
+ targets: npt.NDArray,
+ n_components: int,
+ outdir: Path,
+ impute_option: ImputeOptions,
+) -> dict:
def objective(trial) -> float:
params = {
# number of boosting rounds
diff --git a/src/preface/predict.py b/src/preface/predict.py
index 1427ca2..1328b39 100644
--- a/src/preface/predict.py
+++ b/src/preface/predict.py
@@ -21,58 +21,62 @@ def preface_predict(
# Load model
preface_model: ort.InferenceSession = ort.InferenceSession(model_path)
-
+
# Check metadata for excluded chromosomes
meta = preface_model.get_modelmeta()
custom_props = meta.custom_metadata_map
-
+
if "exclude_chrs" in custom_props:
exclude_str = custom_props["exclude_chrs"]
if exclude_str:
exclude_chrs = exclude_str.split(",")
else:
exclude_chrs = []
- print(f"[dim]Using excluded chromosomes from model metadata: {exclude_chrs}[/dim]")
-
+ print(
+ f"[dim]Using excluded chromosomes from model metadata: {exclude_chrs}[/dim]"
+ )
+
ratios: pd.DataFrame = pd.read_csv(infile, sep="\t")
# Preprocess ratios
preprocessed_ratios = preprocess_ratios(ratios, exclude_chrs=exclude_chrs)
-
+
# Convert to float32
input_data = preprocessed_ratios.values.astype(np.float32)
# Run inference
# We can rely on position 0, 1 or names.
# build_ensemble saves: final_ff_score, final_sex_prob
-
+
# Get output names
output_names = [o.name for o in preface_model.get_outputs()]
-
+
# Run
- results = preface_model.run(output_names, {preface_model.get_inputs()[0].name: input_data})
-
+ results = preface_model.run(
+ output_names, {preface_model.get_inputs()[0].name: input_data}
+ )
+
# Map results to meaningful variables
# If standard PREFACE model, names are specific.
# If unknown model, fallback to index.
-
+
ff_score = None
sex_prob = None
-
+
result_map = dict(zip(output_names, results))
-
+
if "final_ff_score" in result_map:
ff_score = result_map["final_ff_score"][0][0]
elif len(results) > 0:
ff_score = results[0][0][0]
-
+
if "final_sex_prob" in result_map:
sex_prob = result_map["final_sex_prob"][0][0]
elif len(results) > 1:
sex_prob = results[1][0][0]
-
+
sex_class = "Male" if sex_prob > 0.5 else "Female"
print("--- Patient Report ---")
print(f"Predicted FF Score: {ff_score:.4f}")
- print(f"Sex Probability: {sex_prob:.4f} ({sex_class})")
\ No newline at end of file
+ print(f"Sex Probability: {sex_prob:.4f} ({sex_class})")
diff --git a/src/preface/train.py b/src/preface/train.py
index ff9f6f5..3ffe6d0 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -90,7 +90,9 @@ def preface_train(
# parse data
for i, sample in samplesheet_data.iterrows():
- logging.info(f"Processing sample {sample['ID']} ({i + 1}/{len(samplesheet_data)})...") # type: ignore
+ logging.info(
+ f"Processing sample {sample['ID']} ({i + 1}/{len(samplesheet_data)})..." # type: ignore
+ )
if (
not Path(sample["filepath"]).exists()
or not Path(sample["filepath"]).is_file() # noqa: W503
@@ -234,19 +236,19 @@ def preface_train(
# Build ensemble model from fold models
logging.info("Building ensemble model from fold models...")
build_ensemble(
- fold_models,
- x_all.shape[1],
+ fold_models,
+ x_all.shape[1],
out_dir / "PREFACE.onnx",
- metadata={"exclude_chrs": ",".join(exclude_chrs)}
+ metadata={"exclude_chrs": ",".join(exclude_chrs)},
)
# Final evaluation on all training data
logging.info("Evaluating final model on all training data...")
-
+
# Load ONNX model
sess = ort.InferenceSession(out_dir / "PREFACE.onnx")
input_name = sess.get_inputs()[0].name
-
+
# Handle NaNs for evaluation if ZERO strategy was used (since ONNX graph might expect clean input for that case)
if impute == ImputeOptions.ZERO:
x_all_eval = np.nan_to_num(x_all, nan=0.0)
@@ -254,10 +256,10 @@ def preface_train(
x_all_eval = x_all
x_all_eval = x_all_eval.astype(np.float32)
-
+
predictions = sess.run(None, {input_name: x_all_eval})
- y_ff_pred = predictions[0].flatten()
-
+ y_ff_pred = predictions[0].flatten() # type: ignore
+
y_ff_all = y_all[:, 1]
# Use first fold's PCA for visualization
From cf6e458effa12e48ac4c65b2b03dcd42559d6761 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Sun, 28 Dec 2025 20:07:05 +0100
Subject: [PATCH 32/50] Update readme + formatting
---
README.md | 68 +++++++++++++++++++++++++------------
src/preface/lib/ensemble.py | 11 +++---
2 files changed, 50 insertions(+), 29 deletions(-)
diff --git a/README.md b/README.md
index 1bbb4a5..c13e9a0 100644
--- a/README.md
+++ b/README.md
@@ -32,13 +32,18 @@ For training, PREFACE requires a samplesheet file.
## Installation & Setup
-PREFACE is a Python package that can be installed using `pip`.
+PREFACE can be installed using `pip`:
```bash
pip install .
```
-This will install the `PREFACE` command-line tool.
+Alternatively, for a reproducible environment using [pixi](https://pixi.sh):
+
+```bash
+pixi install
+pixi run PREFACE --help
+```
## Model training
@@ -46,28 +51,43 @@ This will install the `PREFACE` command-line tool.
PREFACE train --samplesheet path/to/samplesheet.tsv [optional arguments]
```
-| Optional argument | Function |
-| :--- | :--- |
-| `--impute` | Impute missing values instead of assuming zero. |
-| `--exclude-chrs` | Chromosomes to exclude from training (default: 13, 18, 21, X, Y). |
-| `--nfolds x` | Number of folds for cross-validation (default: 5). |
-| `--nfeat x` | Number of features (PCA components) (default: 50). |
-| `--tune` | Enable automatic hyperparameter tuning. |
-| `--model [neural\|xgboost]` | Type of model to train (default: neural). |
+### Options
+
+| Argument | Type | Default | Function |
+| :--- | :--- | :--- | :--- |
+| `--samplesheet` | PATH | (Required) | Path to the samplesheet TSV file. |
+| `--outdir` | PATH | `.` | Output directory for models and plots. |
+| `--impute` | [zero\|mice\|mean\|median\|knn] | `zero` | Strategy to handle missing values (NaNs). |
+| `--exclude-chrs` | TEXT | `13,18,21,X,Y` | Chromosomes to exclude from training features. |
+| `--nfolds` | INTEGER | `5` | Number of folds for cross-validation. |
+| `--nfeat` | INTEGER | `50` | Number of features (PCA components) to use. |
+| `--tune` | BOOLEAN | `False` | Enable automatic hyperparameter tuning (via Optuna). |
+| `--model` | [neural\|xgboost] | `neural` | Type of model architecture to train. |
## Predicting
```bash
-PREFACE predict --infile path/to/infile.bed --model path/to/model_directory
+PREFACE predict --infile path/to/infile.bed --model path/to/PREFACE.onnx
```
-| Argument | Function |
-| :--- | :--- |
-| `--infile` | Path to input BED file. |
-| `--model` | Path to the trained model directory. |
+### Options
+
+| Argument | Type | Default | Function |
+| :--- | :--- | :--- | :--- |
+| `--infile` | PATH | (Required) | Path to input BED file for prediction. |
+| `--model` | PATH | (Required) | Path to the trained `.onnx` model file. |
-## Model optimization
+The prediction output includes both the predicted fetal fraction score and the fetal sex probability.
+
+## Version
+
+To check the installed version of PREFACE:
+
+```bash
+PREFACE version
+```
+## Model optimization
- The most important parameter is `--nfeat`:
- It represents the number of principal components (PCs) that will be used as features during model training. Depending on the used copy number alteration software, bin size and the number of training samples, it might have different optimal values. In general, I recommend to train a model using the default parameters. The output will contain a plot that enables you to review the selected `--nfeat`. Two parts should be seen in the proportion of variance across the principal components (indexed in order of importance):
- A 'random' phase (representing PCs that explain variance caused by, inter alia, fetal fraction).
@@ -80,7 +100,7 @@ PREFACE predict --infile path/to/infile.bed --model path/to/model_directory
## NPZ to Parquet Converter
-This script converts NumPy `.npz` files into one or more Parquet files, facilitating easier exploration and analysis of the stored numerical data using tools like Pandas.
+Converts NumPy `.npz` files into one or more Parquet files, facilitating easier exploration and analysis using tools like Pandas.
### Usage
@@ -88,12 +108,14 @@ This script converts NumPy `.npz` files into one or more Parquet files, facilita
PREFACE utils npz-to-parquet [ ...] [-o ]
```
-- ` [ ...]`: One or more paths to the input `.npz` files.
-- `-o, --output-dir`: (Optional) Directory to save the output Parquet files. Defaults to the current directory (`.`).
+| Argument | Type | Default | Function |
+| :--- | :--- | :--- | :--- |
+| `npz_files` | ARGUMENT(S) | (Required) | One or more .npz files to convert. |
+| `--output-dir` | PATH | `.` | Directory to save the output Parquet files. |
## FFY Calculator
-Calculates Fetal Fraction from Y-chromosome reads (from WisecondorX NPZ output).
+Calculates Fetal Fraction from Y-chromosome reads (FFY) directly from WisecondorX output files.
### Usage
@@ -101,5 +123,7 @@ Calculates Fetal Fraction from Y-chromosome reads (from WisecondorX NPZ output).
PREFACE utils ffy [--sex-cutoff ]
```
-- ``: Path to WisecondorX output NPZ file.
-- `--sex-cutoff`: (Optional) Cutoff for sex determination (default: 0.2).
\ No newline at end of file
+| Argument | Type | Default | Function |
+| :--- | :--- | :--- | :--- |
+| `wisecondorx_npz`| ARGUMENT | (Required) | Path to WisecondorX output NPZ file. |
+| `--sex-cutoff` | FLOAT | `0.2` | Cutoff for sex determination. |
\ No newline at end of file
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
index 625c7b1..0420831 100644
--- a/src/preface/lib/ensemble.py
+++ b/src/preface/lib/ensemble.py
@@ -94,8 +94,8 @@ def build_ensemble(
if current_model:
# Merge Imputer + PCA
current_model = merge_models(
- current_model,
- pca_onnx,
+ current_model, # type: ignore
+ pca_onnx, # type: ignore
io_map=[(imp_out_name, pca_in_name)], # type: ignore
)
# Update output name
@@ -114,15 +114,12 @@ def build_ensemble(
model_type = "nn" if isinstance(model, Model) else "xgb"
if model_type == "nn":
- # tf2onnx / onnxmltools
- # We explicitly provide input signature to avoid "ValueError: from_keras requires input_signature"
spec = (tf.TensorSpec((None, n_comps), tf.float32, name="input_model"),) # type: ignore
m_onnx, _ = tf2onnx.convert.from_keras(
model, input_signature=spec, opset=12
)
m_onnx.graph.name = f"fold_{i}_model"
- else:
- # XGBoost
+ elif model_type == "xgb":
m_onnx = onnxmltools.convert_xgboost(
model,
initial_types=[("input_model", FloatTensorType([None, n_comps]))],
@@ -133,7 +130,7 @@ def build_ensemble(
# Merge (Imputer+PCA) + Model
current_model = merge_models(
- current_model,
+ current_model, # type: ignore
m_onnx,
io_map=[(current_out_name, m_in_name)], # type: ignore
)
From 59b7217f065f3034a9f5119428d5c6724bffa254 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Mon, 29 Dec 2025 15:12:58 +0100
Subject: [PATCH 33/50] Add PCA and tSNE plotting to CV loop
---
.gitignore | 2 +
.vscode/settings.json | 4 --
src/preface/lib/functions.py | 97 +++++++++++++++++++++++++++++++++++-
src/preface/train.py | 38 ++++++++++++++
4 files changed, 135 insertions(+), 6 deletions(-)
delete mode 100644 .vscode/settings.json
diff --git a/.gitignore b/.gitignore
index 3200a62..514f870 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,8 @@ data/
__pycache__/
.gemini/
*.ipynb
+.vscode/
+.ruff_cache/
# pixi environments
.pixi/*
!.pixi/config.toml
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index ba2a6c0..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "python-envs.defaultEnvManager": "ms-python.python:system",
- "python-envs.pythonProjects": []
-}
\ No newline at end of file
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index ede795d..caaaa36 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -2,9 +2,12 @@
import matplotlib.pyplot as plt
import numpy as np
+import numpy.typing as npt
import pandas as pd
import statsmodels.api as sm
+from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
+from sklearn.manifold import TSNE
from sklearn.metrics import (
mean_absolute_error,
roc_curve,
@@ -245,7 +248,7 @@ def plot_ffx(
y_values: np.ndarray,
intercept: float,
slope: float,
- out_dir_path: Path,
+ output: Path,
):
"""
Plot RLM fit results.
@@ -287,5 +290,95 @@ def plot_ffx(
linewidth=3,
)
plt.tight_layout()
- plt.savefig(out_dir_path / "FFX.png", dpi=300)
+ plt.savefig(output, dpi=300)
+ plt.close()
+
+
+def plot_pca(
+ pca: PCA,
+ principal_components: npt.NDArray,
+ output: Path,
+ labels: list | None = None,
+ title: str = "PCA Plot",
+) -> None:
+ """
+ Generate and save a PCA plot.
+ """
+
+ plt.figure(figsize=(8, 6))
+ if labels is not None:
+ labels = np.asarray(labels)
+ unique_labels = np.unique(labels)
+ for label in unique_labels:
+ indices = np.where(labels == label)
+ plt.scatter(
+ principal_components[indices, 0],
+ principal_components[indices, 1],
+ label=str(label),
+ alpha=0.7,
+ )
+ plt.legend()
+ else:
+ plt.scatter(
+ principal_components[:, 0],
+ principal_components[:, 1],
+ color=COLOR_A,
+ alpha=0.7,
+ )
+
+ plt.xlabel(f"PC1 ({pca.explained_variance_ratio_[0]:.2%} variance)")
+ plt.ylabel(f"PC2 ({pca.explained_variance_ratio_[1]:.2%} variance)")
+ plt.title(title)
+ plt.tight_layout()
+ plt.savefig(output, dpi=300)
+ plt.close()
+
+
+def plot_tsne(
+ data: np.ndarray | pd.DataFrame,
+ output: Path,
+ labels: list | None = None,
+ perplexity: float = 30.0,
+ title: str = "t-SNE Plot",
+) -> None:
+ """
+ Generate and save a t-SNE plot.
+ """
+ # t-SNE requires fewer samples than perplexity usually, handled by sklearn but good to know.
+ # If samples < perplexity, sklearn warns or adjusts.
+ n_samples = data.shape[0]
+ eff_perplexity = min(perplexity, n_samples - 1) if n_samples > 1 else 1.0
+
+ tsne = TSNE(
+ n_components=2,
+ perplexity=eff_perplexity,
+ random_state=42,
+ init="pca",
+ learning_rate="auto",
+ )
+ tsne_results = tsne.fit_transform(data)
+
+ plt.figure(figsize=(8, 6))
+ if labels is not None:
+ labels = np.asarray(labels)
+ unique_labels = np.unique(labels)
+ for label in unique_labels:
+ indices = np.where(labels == label)
+ plt.scatter(
+ tsne_results[indices, 0],
+ tsne_results[indices, 1],
+ label=str(label),
+ alpha=0.7,
+ )
+ plt.legend()
+ else:
+ plt.scatter(
+ tsne_results[:, 0], tsne_results[:, 1], color=COLOR_A, alpha=0.7
+ )
+
+ plt.xlabel("t-SNE dimension 1")
+ plt.ylabel("t-SNE dimension 2")
+ plt.title(title)
+ plt.tight_layout()
+ plt.savefig(output, dpi=300)
plt.close()
diff --git a/src/preface/train.py b/src/preface/train.py
index 3ffe6d0..5a0f859 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -20,6 +20,8 @@
from preface.lib.functions import (
plot_regression_performance,
plot_classification_performance,
+ plot_pca,
+ plot_tsne,
preprocess_ratios,
)
from preface.lib.xgboost import xgboost_tune, xgboost_fit
@@ -34,6 +36,7 @@
class ModelOptions(Enum):
NEURAL = "neural"
XGBOOST = "xgboost"
+ SVM = "svm"
def preface_train(
@@ -139,6 +142,27 @@ def preface_train(
x_all: npt.NDArray = ratios_per_sample.drop(columns=["sex", "ff"]).to_numpy()
y_all: npt.NDArray = ratios_per_sample[["sex", "ff"]].to_numpy()
+ # Run, Plot and export PCA
+ # -> Can't run PCA because the data still contains NaNs at this point
+ # pca_full = PCA(n_components=n_feat)
+ # components = pca_full.fit_transform(x_all)
+ # plot_pca(
+ # pca_full,
+ # principal_components=components,
+ # labels=ratios_per_sample.index.to_list(),
+ # output=out_dir / "pca_full.png",
+ # title="PCA of all training samples",
+ # )
+
+ # Plot and export t-SNE
+ # -> Can't run t-SNE because the data still contains NaNs at this point
+ # plot_tsne(
+ # data=x_all,
+ # labels=ratios_per_sample.index.to_list(),
+ # output=out_dir / "tsne_full.png",
+ # title="t-SNE of all training samples",
+ # )
+
train_params = {}
if tune:
# Enable hyperparameter tuning
@@ -173,6 +197,20 @@ def preface_train(
x_train = fold_pca.fit_transform(x_train)
x_test = fold_pca.transform(x_test)
+ plot_pca(
+ fold_pca,
+ principal_components=x_train,
+ output=out_dir / "training_folds" / f"pca_fold_{fold}.png",
+ title=f"PCA of training fold {fold}",
+ )
+
+ plot_tsne(
+ data=x_train,
+ labels=ratios_per_sample.index.to_list(),
+ output=out_dir / "training_folds" / f"tsne_fold_{fold}.png",
+ title=f"t-SNE of training fold {fold}",
+ )
+
# Train
logging.info(f"Training fold {fold}...")
if model_type == ModelOptions.NEURAL:
From 28552d39ed096951c53bc92dea6a1c2dce5cd4f6 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Mon, 29 Dec 2025 16:39:50 +0100
Subject: [PATCH 34/50] implement ZeroImputer for API coherence
---
src/preface/lib/impute.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index 0ff57fa..0f747c4 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -1,7 +1,6 @@
import logging
from enum import Enum
-import numpy as np
import numpy.typing as npt
import sklearn
from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
@@ -16,9 +15,15 @@ class ImputeOptions(Enum):
KNN = "knn" # impute missing values using k-nearest neighbors
+class ZeroImputer(SimpleImputer):
+ def fit(self, X, y=None):
+ self.fill_value = 0.0
+ return super().fit(X, y)
+
+
def impute_nan(
values: npt.NDArray, method: ImputeOptions
-) -> tuple[npt.NDArray, object]:
+) -> tuple[npt.NDArray, IterativeImputer | SimpleImputer | KNNImputer | ZeroImputer]:
"""
Handle NaN values
Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
@@ -49,9 +54,8 @@ def impute_nan(
# Option 2: Assume missing values are zero (no change)
elif method == ImputeOptions.ZERO:
logging.info("Assuming missing values are zero...")
- imputed_values = np.where(np.isnan(values), 0.0, values)
- # For ZERO, we don't have a sklearn imputer, but we can simulate one or handle it in export
- imputer = None
+ imputer = ZeroImputer()
+ imputed_values = imputer.fit_transform(values)
# Option 3: Impute missing values by calculating mean
elif method == ImputeOptions.MEAN:
From 805e380cecd860011342edcd7246c50942169993 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 13:34:20 +0100
Subject: [PATCH 35/50] replace kfold by shuffle split, drop classification
---
src/preface/lib/ensemble.py | 272 +++++++++++++++++++++--------------
src/preface/lib/functions.py | 55 ++-----
src/preface/lib/impute.py | 10 +-
src/preface/lib/neural.py | 119 +++++++--------
src/preface/lib/svm.py | 79 ++++++++++
src/preface/lib/xgboost.py | 35 ++---
src/preface/train.py | 203 +++++++++++++-------------
7 files changed, 419 insertions(+), 354 deletions(-)
create mode 100644 src/preface/lib/svm.py
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
index 0420831..fad3b6f 100644
--- a/src/preface/lib/ensemble.py
+++ b/src/preface/lib/ensemble.py
@@ -1,5 +1,6 @@
from pathlib import Path
+import numpy as np
import onnx
import onnxmltools
import tensorflow as tf
@@ -9,6 +10,7 @@
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
from sklearn.decomposition import PCA
+from sklearn.svm import SVR, SVC
from tensorflow.keras import Model # type: ignore
from xgboost import XGBRegressor
@@ -25,7 +27,7 @@ def _ensure_opset(model_proto, version=12):
def build_ensemble(
- models: list[tuple[object, PCA, Model | XGBRegressor]],
+ models: list[tuple[object, PCA, Model | XGBRegressor | dict[str, SVR | SVC]]],
input_dim: int,
output_path: Path,
metadata: dict[str, str] | None = None,
@@ -37,81 +39,58 @@ def build_ensemble(
"""
prefixed_models = []
+ fold_info = [] # Store (model_type, reg_base, class_base) for each fold
# Process each fold
for i, (imputer, pca, model) in enumerate(models):
fold_prefix = f"fold_{i}_"
- # 1. Convert Imputer (if exists)
- # Input to Imputer is FloatTensorType([None, input_dim])
+ # Convert Imputer
initial_type = [("input", FloatTensorType([None, input_dim]))]
- if imputer is not None:
- # simple imputer
- imp_onnx = convert_sklearn(
- imputer, initial_types=initial_type, target_opset=12
- )
- _ensure_opset(imp_onnx, 12)
-
- # Rename output of imputer to match input of PCA
- # But wait, we can just chain them via merge_models later?
- # Easier to chain them linearly first or merge step by step.
- current_model = imp_onnx
- # The output name of sklearn models is typically "variable" or similar.
- # We need to find the output name.
- imp_out_name = current_model.graph.output[0].name # type: ignore
- else:
- # No imputer (ZERO strategy). We need a "Identity" or just pass input.
- # However, if we want to fill NaNs with 0, we might need a custom ONNX node or assume input has 0s.
- # For now, let's assume the user handles NaN -> 0 before or use Identity.
- # Actually, `convert_sklearn` handles NaN?
- # If the user selected ZERO, they expect NaNs to be 0.
- # We can create a simple graph that takes input and returns input (Identity),
- # relying on the caller to provide 0s or ONNX runtime to handle it.
- # BETTER: create a dummy identity model.
-
- # For simplicity in this fix, we assume input is already clean if imputer is None,
- # OR we rely on the fact that we can't easily inject "FillNaN(0)" without complex node creation.
- # Let's start with the PCA conversion using the initial type.
- current_model = None
- imp_out_name = "input"
-
- # 2. Convert PCA
- # Input to PCA is the output of Imputer (or "input")
- if current_model:
- # If we have an imputer model, the PCA input type should match its output
- # But convert_sklearn needs `initial_types`.
- # We can convert PCA independently with same shape.
- pca_initial_type = [("input_pca", FloatTensorType([None, input_dim]))]
- else:
- pca_initial_type = initial_type
+ # sklearn imputer
+ imputer_onnx = convert_sklearn(
+ imputer, initial_types=initial_type, target_opset=12
+ )
+ _ensure_opset(imputer_onnx, 12)
+ # Prefix Imputer
+ imputer_onnx = add_prefix(imputer_onnx, prefix="imputer_") # type: ignore
+ imputer_out_name = imputer_onnx.graph.output[0].name # type: ignore
+
+ # Convert PCA
+ # Imputer -> PCA
+ # Use pca.n_features_in_ to handle case where imputer reduced dimensions
+ n_features_pca = getattr(pca, "n_features_in_", input_dim)
+ pca_initial_type = [("input_pca", FloatTensorType([None, n_features_pca]))]
pca_onnx = convert_sklearn(pca, initial_types=pca_initial_type, target_opset=12)
_ensure_opset(pca_onnx, 12)
+
+ # Prefix PCA
+ pca_onnx = add_prefix(pca_onnx, prefix="pca_") # type: ignore
pca_in_name = pca_onnx.graph.input[0].name # type: ignore
pca_out_name = pca_onnx.graph.output[0].name # type: ignore
- if current_model:
- # Merge Imputer + PCA
- current_model = merge_models(
- current_model, # type: ignore
- pca_onnx, # type: ignore
- io_map=[(imp_out_name, pca_in_name)], # type: ignore
- )
- # Update output name
- current_out_name = pca_out_name
- else:
- current_model = pca_onnx
- current_out_name = pca_out_name
- # If we had no imputer, we need to rename the input to "input" to standardize
- # actually pca_onnx input is "input" (from initial_type) or "input_pca".
- # We will handle renaming at the global merge.
+ # Merge Imputer + PCA
+ current_model = merge_models(
+ imputer_onnx, # type: ignore
+ pca_onnx, # type: ignore
+ io_map=[(imputer_out_name, pca_in_name)], # type: ignore
+ )
+ # Update output name
+ current_out_name = pca_out_name
# 3. Convert Model
# Input to Model is PCA output. Shape: [None, n_components]
n_comps = pca.n_components_
- model_type = "nn" if isinstance(model, Model) else "xgb"
+ model_type = "unknown"
+ if isinstance(model, Model):
+ model_type = "nn"
+ elif isinstance(model, (dict, list, tuple)): # Handle dict for SVM
+ model_type = "svm"
+ else:
+ model_type = "xgb"
if model_type == "nn":
spec = (tf.TensorSpec((None, n_comps), tf.float32, name="input_model"),) # type: ignore
@@ -119,6 +98,22 @@ def build_ensemble(
model, input_signature=spec, opset=12
)
m_onnx.graph.name = f"fold_{i}_model"
+
+ # Prefix NN
+ m_onnx = add_prefix(m_onnx, prefix="nn_")
+ m_in_name = m_onnx.graph.input[0].name
+
+ # Merge (Imputer+PCA) + Model
+ current_model = merge_models(
+ current_model, # type: ignore
+ m_onnx,
+ io_map=[(current_out_name, m_in_name)], # type: ignore
+ )
+
+ # Record outputs
+ # Assuming standard naming for NN for now as we can't easily inspect without graph structure knowledge
+ fold_info.append(("nn", "nn_reg_output", "nn_class_output"))
+
elif model_type == "xgb":
m_onnx = onnxmltools.convert_xgboost(
model,
@@ -126,14 +121,86 @@ def build_ensemble(
target_opset=12,
)
- m_in_name = m_onnx.graph.input[0].name
+ # Prefix XGB
+ m_onnx = add_prefix(m_onnx, prefix="xgb_")
+ m_in_name = m_onnx.graph.input[0].name
- # Merge (Imputer+PCA) + Model
- current_model = merge_models(
- current_model, # type: ignore
- m_onnx,
- io_map=[(current_out_name, m_in_name)], # type: ignore
- )
+ # Capture output name
+ xgb_out_base = m_onnx.graph.output[0].name
+
+ # Merge (Imputer+PCA) + Model
+ current_model = merge_models(
+ current_model, # type: ignore
+ m_onnx,
+ io_map=[(current_out_name, m_in_name)], # type: ignore
+ )
+
+ fold_info.append(("xgb", xgb_out_base, None))
+
+ elif model_type == "svm":
+ # Expecting dict with 'SVR' and 'SVC'
+ svr = model["SVR"]
+ svc = model["SVC"]
+
+ # Patch SVR if no support vectors (e.g. large epsilon)
+ if hasattr(svr, "support_vectors_") and svr.support_vectors_.shape[0] == 0:
+ # Add dummy support vector with 0 weight
+ dummy_sv = np.zeros(
+ (1, svr.support_vectors_.shape[1]), dtype=np.float32
+ )
+ svr.support_vectors_ = dummy_sv
+
+ # Patch internal attributes used by coef_ property
+ svr._dual_coef_ = np.zeros((1, 1), dtype=np.float32)
+ svr.dual_coef_ = svr._dual_coef_
+
+ if hasattr(svr, "_n_support"):
+ svr._n_support = np.array([1], dtype=np.int32)
+
+ # Convert SVR
+ svr_onnx = convert_sklearn(
+ svr,
+ initial_types=[("input_svr", FloatTensorType([None, n_comps]))],
+ target_opset=12,
+ )
+ _ensure_opset(svr_onnx, 12)
+
+ # Prefix SVR
+ svr_onnx = add_prefix(svr_onnx, prefix="svr_")
+ svr_in_name = svr_onnx.graph.input[0].name
+ svr_out_base = svr_onnx.graph.output[0].name
+
+ # Convert SVC
+ # zipmap=False is important to get probabilities as tensor
+ svc_onnx = convert_sklearn(
+ svc,
+ initial_types=[("input_svc", FloatTensorType([None, n_comps]))],
+ target_opset=12,
+ options={"zipmap": False},
+ )
+ _ensure_opset(svc_onnx, 12)
+
+ # Prefix SVC
+ svc_onnx = add_prefix(svc_onnx, prefix="svc_")
+ svc_in_name = svc_onnx.graph.input[0].name
+ # Output 0 is label, Output 1 is probabilities (usually)
+ svc_out_base = svc_onnx.graph.output[1].name
+
+ # Combine SVR and SVC into one model (parallel branches)
+ svm_combined = merge_models(svr_onnx, svc_onnx, io_map=[])
+
+ # Merge (Imputer+PCA) with (SVR+SVC)
+ # Connect PCA output to both SVR and SVC inputs
+ current_model = merge_models(
+ current_model,
+ svm_combined,
+ io_map=[
+ (current_out_name, svr_in_name),
+ (current_out_name, svc_in_name),
+ ],
+ )
+
+ fold_info.append(("svm", svr_out_base, svc_out_base))
# Prefix everything in this fold's graph
prefixed_model = add_prefix(current_model, prefix=fold_prefix)
@@ -145,12 +212,6 @@ def build_ensemble(
# Start with the first fold
combined_model = prefixed_models[0]
- # Identify the input name of the first fold
- # It should be "fold_0_input" (if we used "input" name initially)
- # logic: add_prefix adds prefix to all names.
- # The input of the chain was "input" (or "input_pca").
- # So it becomes "fold_0_input".
-
for i in range(1, len(prefixed_models)):
combined_model = merge_models(
combined_model,
@@ -160,10 +221,6 @@ def build_ensemble(
graph = combined_model.graph
- # Now we need to broadcast the global "input" to "fold_0_input", "fold_1_input", ...
- # We create a new input "global_input" and Identity nodes or just rewire?
- # Rewiring is safer.
-
# Find all inputs that look like "fold_X_input" or "fold_X_input_pca"
fold_inputs = []
for node in graph.input:
@@ -172,15 +229,8 @@ def build_ensemble(
# Create a global input
global_input_name = "input"
- # remove existing inputs from graph.input (they become internal nodes fed by global input)
- # Actually, we can just rename them? No, they are distinct nodes in the graph now?
- # If we map them to the same tensor, they get connected.
-
- # Let's add an Identity node for each fold input, fed by global_input
- # Or simpler: create the global input, and add Split? Or just use same name?
- # In ONNX, if multiple nodes use "input", it's valid.
- # So we want to replace all usages of "fold_i_input" with "global_input".
+ # Replace all usages of "fold_i_input" with "global_input".
for node in graph.node:
for idx, input_name in enumerate(node.input):
if input_name in fold_inputs:
@@ -201,42 +251,29 @@ def build_ensemble(
)
# --- Average Outputs ---
- # Identify outputs.
- # NN: fold_i_reg_output, fold_i_class_output
- # XGB: fold_i_variable (output of regressor) -> need to split?
-
- # Note: earlier XGB code said it outputs [Batch, 2] for multi-output.
- # We need to find the output names of the fold graphs.
-
reg_names = []
class_names = []
# Helper to find output names
- for i, (_, _, model) in enumerate(models):
- model_type = "nn" if isinstance(model, Model) else "xgb"
+ for i, (model_type, reg_base, class_base) in enumerate(fold_info):
prefix = f"fold_{i}_"
if model_type == "nn":
# Keras outputs are typically named by layer names.
- # In neural.py: "reg_output", "class_output"
- reg_names.append(prefix + "reg_output")
- class_names.append(prefix + "class_output")
- else:
- # XGBoost multi-output
- # The output name from onnxmltools for XGB is usually "variable"
- xgb_out = prefix + "variable"
+ # We added "nn_" prefix.
+ reg_names.append(prefix + reg_base)
+ class_names.append(prefix + class_base)
+
+ elif model_type == "xgb":
+ # XGBoost output "variable" -> "xgb_variable"
+ xgb_out = prefix + reg_base
# We need to split this output. It is [Batch, 2].
# Column 0: Reg, Column 1: Class (Prob)
- # Add Split node
split_reg = f"{prefix}reg_split"
split_class = f"{prefix}class_split"
- # Create Split node
- # Attributes: axis=1, split=[1,1]
- # Output: [split_reg, split_class]
-
split_node = helper.make_node(
"Split",
inputs=[xgb_out],
@@ -250,6 +287,33 @@ def build_ensemble(
reg_names.append(split_reg)
class_names.append(split_class)
+ elif model_type == "svm":
+ # SVR output "variable" -> "svr_variable"
+ # SVC output "output_probability" -> "svc_output_probability"
+
+ svm_reg_out = prefix + reg_base
+ svm_class_prob_out = prefix + class_base
+
+ reg_names.append(svm_reg_out)
+
+ # SVC probability output is [Batch, 2] (prob class 0, prob class 1).
+ # We need to extract the second column (class 1).
+
+ svm_class_split = f"{prefix}class_prob_split"
+ svm_class_0_dummy = f"{prefix}class_prob_0_dummy"
+
+ split_node_svm = helper.make_node(
+ "Split",
+ inputs=[svm_class_prob_out],
+ outputs=[svm_class_0_dummy, svm_class_split],
+ name=f"{prefix}SVMSplit",
+ axis=1,
+ split=[1, 1],
+ )
+ graph.node.append(split_node_svm)
+
+ class_names.append(svm_class_split)
+
# Add Mean nodes
final_reg_name = "final_ff_score"
final_class_name = "final_sex_prob"
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index caaaa36..7461ebb 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -10,10 +10,6 @@
from sklearn.manifold import TSNE
from sklearn.metrics import (
mean_absolute_error,
- roc_curve,
- auc,
- confusion_matrix,
- ConfusionMatrixDisplay,
)
@@ -33,7 +29,13 @@ def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.Da
# exclude chromosomes
ratios_df = ratios_df[~ratios_df["chr"].isin(exclude_chrs)].copy()
# add region column
- ratios_df["region"] = (ratios_df["chr"] + ":" + ratios_df["start"].astype(str) + "-" + ratios_df["end"].astype(str)) # type: ignore
+ ratios_df["region"] = (
+ ratios_df["chr"]
+ + ":" # type: ignore
+ + ratios_df["start"].astype(str)
+ + "-"
+ + ratios_df["end"].astype(str)
+ ) # type: ignore
# drop chr, start, end columns
ratios_df.drop(columns=["chr", "start", "end"], inplace=True)
# set region as index and transpose
@@ -190,45 +192,6 @@ def plot_regression_performance(
}
-def plot_classification_performance(
- y_prob: np.ndarray,
- y_true: np.ndarray,
- path: Path,
-) -> None:
- """
- Plot classification performance (ROC and Confusion Matrix).
- """
- _, axes = plt.subplots(1, 2, figsize=(10, 5))
-
- # ROC Curve
- ax = axes[0]
- fpr, tpr, _ = roc_curve(y_true, y_prob)
- roc_auc = auc(fpr, tpr)
-
- ax.plot(fpr, tpr, color=COLOR_A, lw=2, label=f"ROC curve (area = {roc_auc:.2f})")
- ax.plot([0, 1], [0, 1], color=COLOR_B, lw=2, linestyle="--")
- ax.set_xlim([0.0, 1.0])
- ax.set_ylim([0.0, 1.05])
- ax.set_xlabel("False Positive Rate")
- ax.set_ylabel("True Positive Rate")
- ax.set_title("Receiver Operating Characteristic")
- ax.legend(loc="lower right")
-
- # Confusion Matrix
- ax = axes[1]
- y_pred = (y_prob >= 0.5).astype(int)
- cm = confusion_matrix(y_true, y_pred)
- disp = ConfusionMatrixDisplay(
- confusion_matrix=cm, display_labels=["Female", "Male"]
- )
- disp.plot(ax=ax, cmap="Blues", colorbar=False)
- ax.set_title("Confusion Matrix")
-
- plt.tight_layout()
- plt.savefig(path, dpi=300)
- plt.close()
-
-
def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
"""
Fit robust linear model (RLM) and return intercept and slope.
@@ -372,9 +335,7 @@ def plot_tsne(
)
plt.legend()
else:
- plt.scatter(
- tsne_results[:, 0], tsne_results[:, 1], color=COLOR_A, alpha=0.7
- )
+ plt.scatter(tsne_results[:, 0], tsne_results[:, 1], color=COLOR_A, alpha=0.7)
plt.xlabel("t-SNE dimension 1")
plt.ylabel("t-SNE dimension 2")
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index 0f747c4..56efc88 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -15,15 +15,9 @@ class ImputeOptions(Enum):
KNN = "knn" # impute missing values using k-nearest neighbors
-class ZeroImputer(SimpleImputer):
- def fit(self, X, y=None):
- self.fill_value = 0.0
- return super().fit(X, y)
-
-
def impute_nan(
values: npt.NDArray, method: ImputeOptions
-) -> tuple[npt.NDArray, IterativeImputer | SimpleImputer | KNNImputer | ZeroImputer]:
+) -> tuple[npt.NDArray, IterativeImputer | SimpleImputer | KNNImputer]:
"""
Handle NaN values
Identify the type of missingness (MCAR, MAR, MNAR). Here we assume MAR.
@@ -54,7 +48,7 @@ def impute_nan(
# Option 2: Assume missing values are zero (no change)
elif method == ImputeOptions.ZERO:
logging.info("Assuming missing values are zero...")
- imputer = ZeroImputer()
+ imputer = SimpleImputer(strategy="constant", fill_value=0.0)
imputed_values = imputer.fit_transform(values)
# Option 3: Impute missing values by calculating mean
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 3a2b790..69eacec 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -4,7 +4,7 @@
import numpy.typing as npt
import optuna
from sklearn.decomposition import PCA
-from sklearn.model_selection import KFold
+from sklearn.model_selection import GroupShuffleSplit
from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
from tensorflow.keras import ( # pylint: disable=no-name-in-module,import-error # type: ignore
Model,
@@ -13,9 +13,36 @@
from preface.lib.impute import ImputeOptions, impute_nan
+def create_model(
+ input_dim: int,
+ n_layers: int,
+ hidden_size: int,
+ learning_rate: float,
+ dropout_rate: float,
+) -> Model:
+ input_layer = layers.Input(shape=(input_dim,))
+ x = input_layer
+ for i in range(n_layers):
+ x = layers.Dense(hidden_size // (2**i), activation="relu")(x) # type: ignore
+ x = layers.Dropout(dropout_rate)(x)
+
+ # regression output
+ reg_out = layers.Dense(1, activation="linear", name="reg_output")(x)
+
+ nn = Model(inputs=input_layer, outputs=reg_out)
+
+ nn.compile(
+ optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
+ loss="mse",
+ loss_weights={"reg_output": 1.0},
+ )
+ return nn
+
+
def neural_tune(
- features: npt.NDArray,
- targets: npt.NDArray,
+ x: npt.NDArray,
+ y: npt.NDArray,
+ groups: npt.NDArray,
n_components: int,
outdir: Path,
impute_option: ImputeOptions,
@@ -29,17 +56,21 @@ def objective(trial) -> float:
"epochs": trial.suggest_int("epochs", 20, 100, step=10),
"batch_size": trial.suggest_int("batch_size", 8, 64, step=8),
}
+ model = create_model(
+ input_dim=x.shape[1],
+ n_layers=params["n_layers"],
+ hidden_size=params["hidden_size"],
+ learning_rate=params["learning_rate"],
+ dropout_rate=params["dropout_rate"],
+ )
# Internal split for the tuner
- kf_internal = KFold(n_splits=3, shuffle=True)
+ gss_internal = GroupShuffleSplit(n_splits=5, test_size=0.2, random_state=42)
scores = []
- for t_idx, v_idx in kf_internal.split(features):
- # Clear session to prevent "tf.function retracing" warning
- keras.backend.clear_session()
-
- x_train, x_val = features[t_idx], features[v_idx]
- y_train, y_val = targets[t_idx], targets[v_idx]
+ for t_idx, v_idx in gss_internal.split(x, y, groups):
+ x_train, x_val = x[t_idx], x[v_idx]
+ y_train, y_val = y[t_idx], y[v_idx]
# impute missing values
x_train, _ = impute_nan(x_train, impute_option)
@@ -50,13 +81,6 @@ def objective(trial) -> float:
x_train = pca.fit_transform(x_train)
x_val = pca.transform(x_val)
- model = multi_output_nn(
- input_dim=x_train.shape[1],
- n_layers=params["n_layers"],
- hidden_size=params["hidden_size"],
- learning_rate=params["learning_rate"],
- dropout_rate=params["dropout_rate"],
- )
history = model.fit(
x_train,
y_train,
@@ -65,7 +89,7 @@ def objective(trial) -> float:
batch_size=params["batch_size"],
callbacks=[
optuna.integration.TFKerasPruningCallback(trial, "val_loss")
- ]
+ ],
)
scores.append(min((history.history["val_loss"])))
@@ -81,42 +105,14 @@ def objective(trial) -> float:
return study.best_params
-def multi_output_nn(
- input_dim: int,
- n_layers: int,
- hidden_size: int,
- learning_rate: float,
- dropout_rate: float,
-) -> Model:
- input_layer = layers.Input(shape=(input_dim,))
- x = input_layer
- for i in range(n_layers):
- x = layers.Dense(hidden_size // (2**i), activation="relu")(x) # type: ignore
- x = layers.Dropout(dropout_rate)(x)
-
- # Head 1: Regression
- reg_out = layers.Dense(1, activation="linear", name="reg_output")(x)
- # Head 2: Classification
- class_out = layers.Dense(1, activation="sigmoid", name="class_output")(x)
-
- nn = Model(inputs=input_layer, outputs=[reg_out, class_out])
-
- nn.compile(
- optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
- loss={"reg_output": "mse", "class_output": "binary_crossentropy"},
- loss_weights={"reg_output": 1.0, "class_output": 1.0},
- )
- return nn
-
-
def neural_fit(
x_train: npt.NDArray,
x_test: npt.NDArray,
y_train: npt.NDArray,
y_test: npt.NDArray,
params: dict,
-) -> tuple[Model, dict]:
- """Build a multi-output neural network for regression and classification."""
+) -> tuple[Model, npt.NDArray]:
+ """Build a neural network for regression."""
# Clear session to prevent "tf.function retracing" warning
keras.backend.clear_session()
@@ -129,13 +125,6 @@ def neural_fit(
}
epochs = params.pop("epochs", 50)
batch_size = params.pop("batch_size", 32)
- # Split targets
- # Assume y[:, 0] = class (sex), y[:, 1] = regression (ff)
- # TODO: this is very brittle, make it more robust
- y_train_reg: npt.NDArray = y_train[:, 1]
- y_train_class: npt.NDArray = y_train[:, 0]
- y_test_reg: npt.NDArray = y_test[:, 1]
- y_test_class: npt.NDArray = y_test[:, 0]
# Early stopping callback
early_stop = keras.callbacks.EarlyStopping(
@@ -143,31 +132,19 @@ def neural_fit(
)
# Create model
- model = multi_output_nn(
- input_dim=x_train.shape[1], **{**nn_default_params, **params}
- )
+ model = create_model(input_dim=x_train.shape[1], **{**nn_default_params, **params})
# Fit model
model.fit(
x_train,
- {"reg_output": y_train_reg, "class_output": y_train_class},
+ y_train,
validation_data=(
x_test,
- {"reg_output": y_test_reg, "class_output": y_test_class},
+ y_test,
),
epochs=epochs,
batch_size=batch_size,
callbacks=[early_stop],
)
- # Evaluate
- predictions = model.predict(x_test)
- reg_preds = predictions[0].flatten()
- class_probs = predictions[1].flatten()
- class_preds = (class_probs >= 0.5).astype(int)
-
- return model, {
- "regression_predictions": reg_preds,
- "class_probabilities": class_probs,
- "class_predictions": class_preds,
- }
+ return model, model.predict(x_test)
diff --git a/src/preface/lib/svm.py b/src/preface/lib/svm.py
new file mode 100644
index 0000000..bbab97e
--- /dev/null
+++ b/src/preface/lib/svm.py
@@ -0,0 +1,79 @@
+import numpy as np
+import numpy.typing as npt
+from pathlib import Path
+from sklearn.metrics import mean_squared_error
+from preface.lib.impute import ImputeOptions, impute_nan
+from sklearn.svm import SVR
+from sklearn.model_selection import GroupShuffleSplit
+from sklearn.decomposition import PCA
+import optuna
+
+
+def svm_tune(
+ x: npt.NDArray, # feature matrix
+ y: npt.NDArray, # target vector
+ groups: npt.NDArray, # group labels for splitting
+ n_components: int, # number of PCA components
+ outdir: Path, # output directory
+ impute_option: ImputeOptions, # imputation strategy
+) -> dict:
+ def objective(trial) -> float:
+ params = {
+ "kernel": "linear",
+ # Regularization parameter
+ "C": trial.suggest_float("C", 0.001, 100, log=True),
+ }
+ model = SVR(**params)
+
+ # Internal split for the tuner
+ gss_internal = GroupShuffleSplit(n_splits=5, test_size=0.2, random_state=42)
+ scores = []
+
+ for _, (train_index, test_index) in enumerate(gss_internal.split(x, y, groups)):
+ x_train, x_val = x[train_index], x[test_index]
+ y_train, y_val = y[train_index], y[test_index]
+
+ # impute missing values
+ x_train, _ = impute_nan(x_train, impute_option)
+ x_val, _ = impute_nan(x_val, impute_option)
+
+ # reduce dimensionality with PCA
+ pca = PCA(n_components=n_components)
+ x_train = pca.fit_transform(x_train)
+ x_val = pca.transform(x_val)
+
+ model.fit(x_train, y_train)
+ preds = model.predict(x_val)
+
+ scores.append(mean_squared_error(y_val, preds))
+
+ return np.mean(scores).astype(float)
+
+ study = optuna.create_study(
+ direction="minimize", pruner=optuna.pruners.MedianPruner()
+ )
+ study.optimize(objective, n_trials=30)
+
+ fig = optuna.visualization.plot_optimization_history(study)
+ fig.write_image(outdir / "svm_tuning_history.png")
+ return study.best_params
+
+
+def svm_fit(
+ x_train: npt.NDArray,
+ x_test: npt.NDArray,
+ y_train: npt.NDArray,
+ y_test: npt.NDArray,
+ params: dict,
+) -> tuple[SVR, npt.NDArray]:
+ """Build a SVM linear model for regression"""
+ # Training parameters
+ svr_default_params = {
+ "kernel": "linear",
+ }
+
+ # Create models
+ model = SVR(**svr_default_params, **params)
+ model.fit(x_train, y_train)
+
+ return model, model.predict(x_test)
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 6308dbb..25a96c5 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -3,7 +3,7 @@
import numpy.typing as npt
import optuna
from sklearn.metrics import mean_squared_error
-from sklearn.model_selection import KFold
+from sklearn.model_selection import GroupShuffleSplit
from tensorflow.keras import ( # type: ignore # pylint: disable=no-name-in-module,import-error
Model,
)
@@ -14,8 +14,9 @@
def xgboost_tune(
- features: npt.NDArray,
- targets: npt.NDArray,
+ x: npt.NDArray,
+ y: npt.NDArray,
+ groups: npt.NDArray,
n_components: int,
outdir: Path,
impute_option: ImputeOptions,
@@ -31,18 +32,18 @@ def objective(trial) -> float:
"subsample": trial.suggest_float("subsample", 0.6, 1.0),
"colsample_bytree": trial.suggest_float("colsample_bytree", 0.6, 1.0),
"tree_method": "hist",
- "multi_strategy": "multi_output_tree",
# random state for reproducibility
"random_state": 42,
}
+ model = XGBRegressor(**params)
# Internal split for the tuner
- kf_internal = KFold(n_splits=3, shuffle=True)
+ gss_internal = GroupShuffleSplit(n_splits=3, test_size=0.2, random_state=42)
scores = []
- for t_idx, v_idx in kf_internal.split(features):
- x_train, x_val = features[t_idx], features[v_idx]
- y_train, y_val = targets[t_idx], targets[v_idx]
+ for _, (train_index, test_index) in enumerate(gss_internal.split(x, y, groups)):
+ x_train, x_val = x[train_index], x[test_index]
+ y_train, y_val = y[train_index], y[test_index]
# impute missing values
x_train, _ = impute_nan(x_train, impute_option)
@@ -54,7 +55,6 @@ def objective(trial) -> float:
x_val = pca.transform(x_val)
# Train and evaluate model
- model = XGBRegressor(**params)
model.fit(x_train, y_train)
preds = model.predict(x_val)
scores.append(mean_squared_error(y_val, preds))
@@ -74,12 +74,11 @@ def xgboost_fit(
y_train: npt.NDArray,
y_test: npt.NDArray,
params: dict,
-) -> tuple[Model, dict]:
- """Build a multi-output xgboost model for regression and classification."""
+) -> tuple[Model, npt.NDArray]:
+ """Build a xgboost model for regression."""
# Training parameters
xgb_default_params = {
"tree_method": "hist",
- "multi_strategy": "multi_output_tree",
"n_estimators": 100,
"max_depth": 6,
"learning_rate": 0.1,
@@ -96,14 +95,4 @@ def xgboost_fit(
# Fit model
model.fit(x_train, y_train, eval_set=[(x_test, y_test)])
- # Evaluate
- preds = model.predict(x_test)
- reg_preds = preds[:, 0]
- class_probs = preds[:, 1]
- class_preds = (class_probs > 0.5).astype(int)
-
- return model, {
- "regression_predictions": reg_preds,
- "class_probabilities": class_probs,
- "class_predictions": class_preds,
- }
+ return model, model.predict(x_test)
diff --git a/src/preface/train.py b/src/preface/train.py
index 5a0f859..79ee224 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -13,18 +13,18 @@
import numpy.typing as npt
import onnxruntime as ort
from sklearn.decomposition import PCA
-from sklearn.metrics import f1_score, mean_absolute_error, r2_score, roc_auc_score
-from sklearn.model_selection import KFold
+from sklearn.metrics import mean_absolute_error, r2_score
+from sklearn.model_selection import GroupShuffleSplit
from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
from preface.lib.functions import (
plot_regression_performance,
- plot_classification_performance,
plot_pca,
plot_tsne,
preprocess_ratios,
)
from preface.lib.xgboost import xgboost_tune, xgboost_fit
+from preface.lib.svm import svm_tune, svm_fit
from preface.lib.neural import neural_tune, neural_fit
from preface.lib.impute import ImputeOptions, impute_nan
from preface.lib.ensemble import build_ensemble
@@ -52,8 +52,8 @@ def preface_train(
EXCLUDE_CHRS, "--exclude-chrs", help="Chromosomes to exclude from training"
),
# cross validation options
- n_folds: int = typer.Option(
- 5, "--nfolds", help="Number of folds for cross-validation"
+ n_splits: int = typer.Option(
+ 50, "--nsplits", help="Number of splits for cross-validation"
),
# PCA options
n_feat: int = typer.Option(
@@ -136,83 +136,101 @@ def preface_train(
# set index to ID column
ratios_per_sample = ratios_per_sample.set_index("id")
+ # Check missingness
+ # Drop columns with more than 1% missing values
+ missingness = ratios_per_sample.isnull().mean()
+ cols_to_drop = missingness[missingness > 0.01].index
+ if len(cols_to_drop) > 0:
+ logging.warning(
+ f"Dropping {len(cols_to_drop)} bins with more than 1% missing values."
+ )
+ ratios_per_sample = ratios_per_sample.drop(columns=cols_to_drop)
+
logging.info("Creating training frame...")
# Split into features and labels
- x_all: npt.NDArray = ratios_per_sample.drop(columns=["sex", "ff"]).to_numpy()
- y_all: npt.NDArray = ratios_per_sample[["sex", "ff"]].to_numpy()
-
- # Run, Plot and export PCA
- # -> Can't run PCA because the data still contains NaNs at this point
- # pca_full = PCA(n_components=n_feat)
- # components = pca_full.fit_transform(x_all)
- # plot_pca(
- # pca_full,
- # principal_components=components,
- # labels=ratios_per_sample.index.to_list(),
- # output=out_dir / "pca_full.png",
- # title="PCA of all training samples",
- # )
-
- # Plot and export t-SNE
- # -> Can't run t-SNE because the data still contains NaNs at this point
- # plot_tsne(
- # data=x_all,
- # labels=ratios_per_sample.index.to_list(),
- # output=out_dir / "tsne_full.png",
- # title="t-SNE of all training samples",
- # )
+ target_cols = ["sex", "ff"]
+ x: npt.NDArray = ratios_per_sample.drop(columns=target_cols).to_numpy()
+ # x_male: npt.NDArray = ratios_per_sample[ratios_per_sample["sex"] == 1].drop(columns=target_cols).to_numpy()
+ # x_female: npt.NDArray = ratios_per_sample[ratios_per_sample["sex"] == 0].drop(columns=target_cols).to_numpy()
+ y: npt.NDArray = ratios_per_sample[["ff"]].to_numpy()
+ # y_male: npt.NDArray = ratios_per_sample[ratios_per_sample["sex"] == 1][["ff"]].to_numpy()
+ # y_female: npt.NDArray = ratios_per_sample[ratios_per_sample["sex"] == 0][["ff"]].to_numpy()
+
+ # Generate bins for the target
+ # prevent data leakage and keep the distribution
+ groups = np.digitize(y, bins=np.percentile(y, [25, 50, 75]))
train_params = {}
if tune:
# Enable hyperparameter tuning
logging.info("Tuning hyperparameters...")
- tuner = neural_tune if model_type == ModelOptions.NEURAL else xgboost_tune
- train_params = tuner(x_all, y_all, n_feat, out_dir, impute)
+ if model_type == ModelOptions.NEURAL:
+ logging.info("Tuning neural network hyperparameters...")
+ tuner = neural_tune
+ elif model_type == ModelOptions.XGBOOST:
+ logging.info("Tuning XGBoost hyperparameters...")
+ tuner = xgboost_tune
+ elif model_type == ModelOptions.SVM:
+ logging.info("Tuning SVM hyperparameters...")
+ tuner = svm_tune
+ else:
+ logging.error("Invalid model type specified for tuning.")
+ raise typer.Exit(code=1)
- # Set up training (k-fold cross-validation)
- # Create directory to store fold metrics
- os.makedirs(out_dir / "training_folds", exist_ok=True)
- fold_metrics = []
- fold_models: list[tuple[object, PCA, keras.Model]] = []
+ train_params = tuner(
+ x=x,
+ y=y,
+ groups=groups,
+ n_components=n_feat,
+ outdir=out_dir,
+ impute_option=impute,
+ )
- # Set up k-fold cross-validation
- kf: KFold = KFold(n_splits=n_folds, shuffle=True, random_state=42)
- for fold, (train_idx, test_idx) in enumerate(kf.split(x_all), 1):
- logging.info(f"Processing Fold {fold}/{n_folds}...")
+ # Set up training (cross-validation)
+ # Create directory to store split metrics
+ os.makedirs(out_dir / "training_splits", exist_ok=True)
+ split_metrics = []
+ split_models: list[tuple[object, PCA, keras.Model]] = []
- # split into train and test sets
- x_train, x_test = x_all[train_idx], x_all[test_idx]
- y_train, y_test = y_all[train_idx], y_all[test_idx]
+ # Set up cross-validation
+ gss: GroupShuffleSplit = GroupShuffleSplit(
+ n_splits=n_splits, test_size=0.2, random_state=42
+ )
+ for split, (train_idx, test_idx) in enumerate(gss.split(x, y, groups), 1):
+ logging.info(f"Processing split {split}/{n_splits}...")
- y_test_class: npt.NDArray = y_test[:, 0]
- y_test_reg: npt.NDArray = y_test[:, 1]
+ # split into train and test sets
+ x_train, x_test = x[train_idx], x[test_idx]
+ y_train, y_test = y[train_idx], y[test_idx]
# impute data
x_train, imputer = impute_nan(x_train, impute)
x_test, _ = impute_nan(x_test, impute)
- # reduce dimensionality with PCA for each fold to prevent data leakage
- fold_pca = PCA(n_components=n_feat)
- x_train = fold_pca.fit_transform(x_train)
- x_test = fold_pca.transform(x_test)
+ # reduce dimensionality with PCA for each split to prevent data leakage
+ split_pca = PCA(n_components=n_feat)
+ x_train = split_pca.fit_transform(x_train)
+ x_test = split_pca.transform(x_test)
+
+ train_labels = ratios_per_sample.index.to_numpy()[train_idx].tolist()
plot_pca(
- fold_pca,
+ split_pca,
principal_components=x_train,
- output=out_dir / "training_folds" / f"pca_fold_{fold}.png",
- title=f"PCA of training fold {fold}",
+ output=out_dir / "training_splits" / f"pca_split_{split}.png",
+ title=f"PCA of training split {split}",
)
plot_tsne(
data=x_train,
- labels=ratios_per_sample.index.to_list(),
- output=out_dir / "training_folds" / f"tsne_fold_{fold}.png",
- title=f"t-SNE of training fold {fold}",
+ labels=train_labels,
+ output=out_dir / "training_splits" / f"tsne_split_{split}.png",
+ title=f"t-SNE of training split {split}",
)
# Train
- logging.info(f"Training fold {fold}...")
+ logging.info(f"Training split {split}...")
if model_type == ModelOptions.NEURAL:
model, predictions = neural_fit(
x_train,
@@ -221,61 +239,54 @@ def preface_train(
y_test,
train_params,
)
- # Save fold model
- model.save(out_dir / "training_folds" / f"fold_{fold}.keras") # type: ignore
elif model_type == ModelOptions.XGBOOST:
model, predictions = xgboost_fit(
x_train, x_test, y_train, y_test, train_params
)
- model.save_model(out_dir / "training_folds" / f"fold_{fold}.bin") # type: ignore
- fold_models.append((imputer, fold_pca, model))
+ elif model_type == ModelOptions.SVM:
+ model, predictions = svm_fit(x_train, x_test, y_train, y_test, train_params)
+
+ else:
+ logging.error("Invalid model type specified for training.")
+ raise typer.Exit(code=1)
+ split_models.append((imputer, split_pca, model))
# Plot regression performance
reg_perf = plot_regression_performance(
- predictions["regression_predictions"],
- y_test_reg,
- fold_pca.explained_variance_ratio_,
+ predictions,
+ y_test,
+ split_pca.explained_variance_ratio_,
n_feat,
"PREFACE (%)",
"FF (%)",
- out_dir / "training_folds" / f"fold_{fold}_regression.png",
- )
-
- # Plot classification performance
- plot_classification_performance(
- predictions["class_probabilities"],
- y_test_class,
- out_dir / "training_folds" / f"fold_{fold}_classification.png",
+ out_dir / "training_splits" / f"split_{split}_regression.png",
)
# return metrics
metrics: dict = {
- # fold number
- "fold": fold,
+ # split number
+ "split": split,
# regression metrics
"ff_mae": mean_absolute_error(
- y_test_reg, predictions["regression_predictions"]
+ y_test, predictions["regression_predictions"]
),
- "ff_r2": r2_score(y_test_reg, predictions["regression_predictions"]),
+ "ff_r2": r2_score(y_test, predictions["regression_predictions"]),
"ff_intercept": reg_perf["intercept"],
"ff_slope": reg_perf["slope"],
- # classification metrics
- "sex_f1": f1_score(y_test_class, predictions["class_predictions"]),
- "sex_auc": roc_auc_score(y_test_class, predictions["class_probabilities"]),
}
- fold_metrics.append(metrics)
+ split_metrics.append(metrics)
- # Save fold metrics to a DataFrame
- fold_metrics_df = pd.DataFrame(fold_metrics)
- fold_metrics_df.to_csv(out_dir / "training_fold_metrics.csv", index=False)
+ # Save split metrics to a DataFrame
+ split_metrics_df = pd.DataFrame(split_metrics)
+ split_metrics_df.to_csv(out_dir / "training_split_metrics.csv", index=False)
- # Build ensemble model from fold models
- logging.info("Building ensemble model from fold models...")
+ # Build ensemble model from split models
+ logging.info("Building ensemble model from split models...")
build_ensemble(
- fold_models,
- x_all.shape[1],
+ split_models,
+ x.shape[1],
out_dir / "PREFACE.onnx",
metadata={"exclude_chrs": ",".join(exclude_chrs)},
)
@@ -286,26 +297,16 @@ def preface_train(
# Load ONNX model
sess = ort.InferenceSession(out_dir / "PREFACE.onnx")
input_name = sess.get_inputs()[0].name
-
- # Handle NaNs for evaluation if ZERO strategy was used (since ONNX graph might expect clean input for that case)
- if impute == ImputeOptions.ZERO:
- x_all_eval = np.nan_to_num(x_all, nan=0.0)
- else:
- x_all_eval = x_all
-
- x_all_eval = x_all_eval.astype(np.float32)
+ x_all_eval = x.astype(np.float32)
predictions = sess.run(None, {input_name: x_all_eval})
- y_ff_pred = predictions[0].flatten() # type: ignore
-
- y_ff_all = y_all[:, 1]
-
- # Use first fold's PCA for visualization
- first_pca = fold_models[0][1]
+
+ # Use first split's PCA for visualization
+ first_pca = split_models[0][1]
info_overall = plot_regression_performance(
- y_ff_pred,
- y_ff_all,
+ predictions[0], # type: ignore
+ y,
first_pca.explained_variance_ratio_,
n_feat,
"PREFACE (%)",
From e67ace0330258a6b1bc5b4febade1436a0b2995d Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 14:28:37 +0100
Subject: [PATCH 36/50] add neural_export
---
src/preface/lib/neural.py | 12 +++++++++++
tests/test_neural_export.py | 41 +++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
create mode 100644 tests/test_neural_export.py
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 69eacec..3037919 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -2,7 +2,10 @@
import numpy as np
import numpy.typing as npt
+import onnx
import optuna
+import tensorflow as tf
+import tf2onnx
from sklearn.decomposition import PCA
from sklearn.model_selection import GroupShuffleSplit
from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
@@ -148,3 +151,12 @@ def neural_fit(
)
return model, model.predict(x_test)
+
+
+def neural_export(model: Model) -> onnx.ModelProto:
+ """Export neural network to ONNX format."""
+ input_signature = [tf.TensorSpec(model.input_shape, tf.float32, name="neural_input")]
+ onnx_model, _ = tf2onnx.convert.from_keras(
+ model, input_signature=input_signature, opset=13
+ )
+ return onnx_model
diff --git a/tests/test_neural_export.py b/tests/test_neural_export.py
new file mode 100644
index 0000000..c6975f9
--- /dev/null
+++ b/tests/test_neural_export.py
@@ -0,0 +1,41 @@
+import unittest
+import onnx
+from preface.lib.neural import create_model, neural_export
+
+
+class TestNeuralExport(unittest.TestCase):
+ def test_neural_export(self):
+ # 1. Create a dummy model
+ input_dim = 10
+ n_layers = 2
+ hidden_size = 32
+ learning_rate = 0.001
+ dropout_rate = 0.2
+
+ model = create_model(
+ input_dim=input_dim,
+ n_layers=n_layers,
+ hidden_size=hidden_size,
+ learning_rate=learning_rate,
+ dropout_rate=dropout_rate,
+ )
+
+ # 2. Export to ONNX
+ onnx_model = neural_export(model)
+
+ # 3. Verify
+ self.assertIsInstance(onnx_model, onnx.ModelProto)
+
+ # Check if the graph has nodes
+ self.assertGreater(len(onnx_model.graph.node), 0)
+
+ # Check inputs
+ self.assertEqual(len(onnx_model.graph.input), 1)
+ self.assertEqual(onnx_model.graph.input[0].name, "neural_input")
+
+ # Validate the model using onnx.checker
+ onnx.checker.check_model(onnx_model)
+
+
+if __name__ == "__main__":
+ unittest.main()
From 43a130644fa96fedb1eb608a0509c092df165121 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 15:33:18 +0100
Subject: [PATCH 37/50] add xgboost export (failing tests)
---
src/preface/lib/xgboost.py | 22 +++++++++++++++++-----
src/preface/train.py | 2 +-
tests/test_xgboost_export.py | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 52 insertions(+), 6 deletions(-)
create mode 100644 tests/test_xgboost_export.py
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 25a96c5..b93d5f1 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -1,14 +1,14 @@
from pathlib import Path
import numpy as np
import numpy.typing as npt
+import onnx
import optuna
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import GroupShuffleSplit
-from tensorflow.keras import ( # type: ignore # pylint: disable=no-name-in-module,import-error
- Model,
-)
from xgboost import XGBRegressor
from sklearn.decomposition import PCA
+import onnxmltools
+from skl2onnx.common.data_types import FloatTensorType
from preface.lib.impute import impute_nan, ImputeOptions
@@ -34,6 +34,8 @@ def objective(trial) -> float:
"tree_method": "hist",
# random state for reproducibility
"random_state": 42,
+ # base score
+ "base_score": 0.5,
}
model = XGBRegressor(**params)
@@ -74,7 +76,7 @@ def xgboost_fit(
y_train: npt.NDArray,
y_test: npt.NDArray,
params: dict,
-) -> tuple[Model, npt.NDArray]:
+) -> tuple[XGBRegressor, npt.NDArray]:
"""Build a xgboost model for regression."""
# Training parameters
xgb_default_params = {
@@ -84,6 +86,7 @@ def xgboost_fit(
"learning_rate": 0.1,
"random_state": 42,
"early_stopping_rounds": 10,
+ "base_score": 0.5,
}
# Create model
@@ -94,5 +97,14 @@ def xgboost_fit(
# Fit model
model.fit(x_train, y_train, eval_set=[(x_test, y_test)])
-
return model, model.predict(x_test)
+
+
+def xgboost_export(model: XGBRegressor) -> onnx.ModelProto:
+ """Export XGBoost model to ONNX format."""
+
+ initial_type = [("input", FloatTensorType([None, model.n_features_in_]))]
+ onnx_model = onnxmltools.convert_xgboost(
+ model, initial_types=initial_type, target_opset=12
+ )
+ return onnx_model
diff --git a/src/preface/train.py b/src/preface/train.py
index 79ee224..62c6f85 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -300,7 +300,7 @@ def preface_train(
x_all_eval = x.astype(np.float32)
predictions = sess.run(None, {input_name: x_all_eval})
-
+
# Use first split's PCA for visualization
first_pca = split_models[0][1]
diff --git a/tests/test_xgboost_export.py b/tests/test_xgboost_export.py
new file mode 100644
index 0000000..32c12b8
--- /dev/null
+++ b/tests/test_xgboost_export.py
@@ -0,0 +1,34 @@
+import unittest
+import numpy as np
+import onnx
+from xgboost import XGBRegressor
+from preface.lib.xgboost import xgboost_export
+
+
+class TestXGBoostExport(unittest.TestCase):
+ def test_xgboost_export(self):
+ # 1. Create dummy data and train a model
+ n_samples = 100
+ n_features = 10
+ x_train = np.random.rand(n_samples, n_features).astype(np.float32)
+ y_train = np.random.rand(n_samples).astype(np.float32)
+
+ model = XGBRegressor(n_estimators=3, max_depth=3, base_score=0.5, random_state=42)
+ model.fit(x_train, y_train)
+
+ # 2. Export to ONNX
+ onnx_model = xgboost_export(model)
+
+ # 3. Verify
+ self.assertIsInstance(onnx_model, onnx.ModelProto)
+
+ # Check graph properties
+ self.assertGreater(len(onnx_model.graph.node), 0)
+ self.assertEqual(len(onnx_model.graph.input), 1)
+ self.assertEqual(onnx_model.graph.input[0].name, "input")
+
+ # Validate the model
+ onnx.checker.check_model(onnx_model)
+
+if __name__ == "__main__":
+ unittest.main()
From 01683f5cc8ecc144825baaf318a5eddce5c2de20 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 15:45:40 +0100
Subject: [PATCH 38/50] amend neural export
---
src/preface/lib/neural.py | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 3037919..c087f4e 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -3,9 +3,8 @@
import numpy as np
import numpy.typing as npt
import onnx
+import onnxmltools
import optuna
-import tensorflow as tf
-import tf2onnx
from sklearn.decomposition import PCA
from sklearn.model_selection import GroupShuffleSplit
from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
@@ -14,6 +13,7 @@
layers,
)
from preface.lib.impute import ImputeOptions, impute_nan
+from onnxmltools.convert.common.data_types import FloatTensorType
def create_model(
@@ -155,8 +155,6 @@ def neural_fit(
def neural_export(model: Model) -> onnx.ModelProto:
"""Export neural network to ONNX format."""
- input_signature = [tf.TensorSpec(model.input_shape, tf.float32, name="neural_input")]
- onnx_model, _ = tf2onnx.convert.from_keras(
- model, input_signature=input_signature, opset=13
- )
+ initial_type = [("neural_input", FloatTensorType([None, model.input_shape[1]]))]
+ onnx_model = onnxmltools.convert_keras(model, initial_types=initial_type, target_opset=12)
return onnx_model
From b328075752764e62aee2eec00c16db915de4be82 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 15:53:47 +0100
Subject: [PATCH 39/50] add svm export
---
src/preface/lib/svm.py | 14 +++++++++++++-
tests/test_svm_export.py | 37 ++++++++++++++++++++++++++++++++++++
tests/test_xgboost_export.py | 15 +++++++++------
3 files changed, 59 insertions(+), 7 deletions(-)
create mode 100644 tests/test_svm_export.py
diff --git a/src/preface/lib/svm.py b/src/preface/lib/svm.py
index bbab97e..88b8c25 100644
--- a/src/preface/lib/svm.py
+++ b/src/preface/lib/svm.py
@@ -7,6 +7,9 @@
from sklearn.model_selection import GroupShuffleSplit
from sklearn.decomposition import PCA
import optuna
+import onnxmltools
+import onnx
+from skl2onnx.common.data_types import FloatTensorType
def svm_tune(
@@ -74,6 +77,15 @@ def svm_fit(
# Create models
model = SVR(**svr_default_params, **params)
- model.fit(x_train, y_train)
+ model.fit(x_train, y_train.ravel())
return model, model.predict(x_test)
+
+
+def svm_export(model: SVR) -> onnx.ModelProto:
+ """Export SVM model to ONNX format."""
+ initial_type = [("svm_input", FloatTensorType([None, model.n_features_in_]))]
+ onnx_model = onnxmltools.convert_sklearn(
+ model, initial_types=initial_type, target_opset=12
+ )
+ return onnx_model # type: ignore
diff --git a/tests/test_svm_export.py b/tests/test_svm_export.py
new file mode 100644
index 0000000..fec3ecd
--- /dev/null
+++ b/tests/test_svm_export.py
@@ -0,0 +1,37 @@
+import unittest
+import numpy as np
+import onnx
+from preface.lib.svm import svm_export, svm_fit
+
+
+class TestSvmExport(unittest.TestCase):
+ def test_svm_export(self):
+ # 1. Create dummy data
+ n_samples = 100
+ n_features = 10
+ x_train = np.random.rand(n_samples, n_features).astype(np.float32)
+ y_train = np.random.rand(n_samples, 1).astype(np.float32)
+ x_test = np.random.rand(n_samples, n_features).astype(np.float32)
+ y_test = np.random.rand(n_samples, 1).astype(np.float32)
+
+ # 2. Train a model using svm_fit
+ model, _ = svm_fit(x_train, x_test, y_train, y_test, params={})
+
+ # 3. Export to ONNX
+ onnx_model = svm_export(model)
+
+ # 4. Verify
+ self.assertIsInstance(onnx_model, onnx.ModelProto)
+
+ # Check graph properties
+ self.assertGreater(len(onnx_model.graph.node), 0)
+ self.assertEqual(len(onnx_model.graph.input), 1)
+ self.assertEqual(len(onnx_model.graph.output), 1)
+ self.assertEqual(onnx_model.graph.input[0].name, "svm_input")
+
+ # Validate the model
+ onnx.checker.check_model(onnx_model)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_xgboost_export.py b/tests/test_xgboost_export.py
index 32c12b8..84e9064 100644
--- a/tests/test_xgboost_export.py
+++ b/tests/test_xgboost_export.py
@@ -12,23 +12,26 @@ def test_xgboost_export(self):
n_features = 10
x_train = np.random.rand(n_samples, n_features).astype(np.float32)
y_train = np.random.rand(n_samples).astype(np.float32)
-
- model = XGBRegressor(n_estimators=3, max_depth=3, base_score=0.5, random_state=42)
+
+ model = XGBRegressor(
+ n_estimators=3, max_depth=3, base_score=0.5, random_state=42
+ )
model.fit(x_train, y_train)
-
+
# 2. Export to ONNX
onnx_model = xgboost_export(model)
# 3. Verify
self.assertIsInstance(onnx_model, onnx.ModelProto)
-
+
# Check graph properties
self.assertGreater(len(onnx_model.graph.node), 0)
self.assertEqual(len(onnx_model.graph.input), 1)
- self.assertEqual(onnx_model.graph.input[0].name, "input")
-
+ self.assertEqual(onnx_model.graph.input[0].name, "xgboost_input")
+
# Validate the model
onnx.checker.check_model(onnx_model)
+
if __name__ == "__main__":
unittest.main()
From 9b4111c56f799cbc5f2392642c77ce4cae80b1d8 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 16:12:16 +0100
Subject: [PATCH 40/50] fix opset
---
src/preface/lib/functions.py | 10 +++++++
src/preface/lib/impute.py | 19 +++++++++++++
src/preface/lib/neural.py | 4 ++-
src/preface/lib/svm.py | 2 +-
src/preface/lib/xgboost.py | 6 ++--
tests/test_functions.py | 36 +++++++++++++++++++++++
tests/test_impute_export.py | 55 ++++++++++++++++++++++++++++++++++++
7 files changed, 127 insertions(+), 5 deletions(-)
create mode 100644 tests/test_functions.py
create mode 100644 tests/test_impute_export.py
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index 7461ebb..eba889a 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -3,8 +3,11 @@
import matplotlib.pyplot as plt
import numpy as np
import numpy.typing as npt
+import onnx
import pandas as pd
import statsmodels.api as sm
+from skl2onnx import convert_sklearn
+from skl2onnx.common.data_types import FloatTensorType
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from sklearn.manifold import TSNE
@@ -343,3 +346,10 @@ def plot_tsne(
plt.tight_layout()
plt.savefig(output, dpi=300)
plt.close()
+
+
+def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
+ """Export PCA model to ONNX format."""
+ initial_type = [("input", FloatTensorType([None, input_dim]))]
+ pca_onnx = convert_sklearn(pca, initial_types=initial_type, target_opset=18)
+ return pca_onnx # type: ignore
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index 56efc88..e567588 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -5,6 +5,9 @@
import sklearn
from sklearn.experimental import enable_iterative_imputer # pylint: disable=unused-import # noqa: F401 # type: ignore
from sklearn.impute import IterativeImputer, KNNImputer, SimpleImputer
+import onnx
+from skl2onnx import convert_sklearn
+from skl2onnx.common.data_types import FloatTensorType
class ImputeOptions(Enum):
@@ -70,3 +73,19 @@ def impute_nan(
imputed_values = imputer.fit_transform(values)
return imputed_values, imputer
+
+
+def impute_export(
+ imputer: SimpleImputer | KNNImputer | IterativeImputer,
+ input_dim: int,
+) -> onnx.ModelProto:
+ """Export imputer to ONNX format."""
+ if isinstance(imputer, IterativeImputer):
+ raise NotImplementedError(
+ "IterativeImputer (MICE) is not supported for ONNX export."
+ )
+
+ initial_type = [("impute_input", FloatTensorType([None, input_dim]))]
+
+ imputer_onnx = convert_sklearn(imputer, initial_types=initial_type, target_opset=18)
+ return imputer_onnx # type: ignore
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index c087f4e..3d6cc57 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -156,5 +156,7 @@ def neural_fit(
def neural_export(model: Model) -> onnx.ModelProto:
"""Export neural network to ONNX format."""
initial_type = [("neural_input", FloatTensorType([None, model.input_shape[1]]))]
- onnx_model = onnxmltools.convert_keras(model, initial_types=initial_type, target_opset=12)
+ onnx_model = onnxmltools.convert_keras(
+ model, initial_types=initial_type, target_opset=18
+ )
return onnx_model
diff --git a/src/preface/lib/svm.py b/src/preface/lib/svm.py
index 88b8c25..dea48a9 100644
--- a/src/preface/lib/svm.py
+++ b/src/preface/lib/svm.py
@@ -86,6 +86,6 @@ def svm_export(model: SVR) -> onnx.ModelProto:
"""Export SVM model to ONNX format."""
initial_type = [("svm_input", FloatTensorType([None, model.n_features_in_]))]
onnx_model = onnxmltools.convert_sklearn(
- model, initial_types=initial_type, target_opset=12
+ model, initial_types=initial_type, target_opset=18
)
return onnx_model # type: ignore
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index b93d5f1..39c70e1 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -8,7 +8,7 @@
from xgboost import XGBRegressor
from sklearn.decomposition import PCA
import onnxmltools
-from skl2onnx.common.data_types import FloatTensorType
+from onnxmltools.convert.common.data_types import FloatTensorType
from preface.lib.impute import impute_nan, ImputeOptions
@@ -103,8 +103,8 @@ def xgboost_fit(
def xgboost_export(model: XGBRegressor) -> onnx.ModelProto:
"""Export XGBoost model to ONNX format."""
- initial_type = [("input", FloatTensorType([None, model.n_features_in_]))]
+ initial_type = [("xgboost_input", FloatTensorType([None, model.n_features_in_]))]
onnx_model = onnxmltools.convert_xgboost(
- model, initial_types=initial_type, target_opset=12
+ model, initial_types=initial_type, target_opset=18
)
return onnx_model
diff --git a/tests/test_functions.py b/tests/test_functions.py
new file mode 100644
index 0000000..1d6fd51
--- /dev/null
+++ b/tests/test_functions.py
@@ -0,0 +1,36 @@
+import unittest
+import numpy as np
+import onnx
+from sklearn.decomposition import PCA
+from preface.lib.functions import pca_export
+
+
+class TestPcaExport(unittest.TestCase):
+ def test_pca_export(self):
+ # 1. Create dummy data and fit a PCA model
+ n_samples = 100
+ n_features = 20
+ n_components = 5
+ data = np.random.rand(n_samples, n_features).astype(np.float32)
+
+ pca = PCA(n_components=n_components)
+ pca.fit(data)
+
+ # 2. Export to ONNX
+ onnx_model = pca_export(pca, n_features)
+
+ # 3. Verify
+ self.assertIsInstance(onnx_model, onnx.ModelProto)
+
+ # Check graph properties
+ self.assertGreater(len(onnx_model.graph.node), 0)
+ self.assertEqual(len(onnx_model.graph.input), 1)
+ self.assertEqual(onnx_model.graph.input[0].name, "input")
+ self.assertEqual(len(onnx_model.graph.output), 1)
+
+ # Validate the model
+ onnx.checker.check_model(onnx_model)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_impute_export.py b/tests/test_impute_export.py
new file mode 100644
index 0000000..3f2cdb7
--- /dev/null
+++ b/tests/test_impute_export.py
@@ -0,0 +1,55 @@
+import unittest
+import numpy as np
+import onnx
+from preface.lib.impute import impute_nan, impute_export, ImputeOptions
+
+
+class TestImputeExport(unittest.TestCase):
+ def setUp(self):
+ self.n_samples = 50
+ self.n_features = 5
+ self.data = np.random.rand(self.n_samples, self.n_features).astype(np.float32)
+ # Introduce NaNs
+ self.data[5, 2] = np.nan
+ self.data[10, 0] = np.nan
+ self.data[25, 4] = np.nan
+
+ def _run_export_test(self, imputer):
+ """Helper to run ONNX export and validation."""
+ self.assertIsNotNone(imputer)
+ onnx_model = impute_export(imputer, self.n_features)
+
+ self.assertIsInstance(onnx_model, onnx.ModelProto)
+ self.assertGreater(len(onnx_model.graph.node), 0)
+ self.assertEqual(len(onnx_model.graph.input), 1)
+ onnx.checker.check_model(onnx_model)
+
+ def test_export_simple_imputer_mean(self):
+ """Test ONNX export for SimpleImputer with 'mean' strategy."""
+ _, imputer = impute_nan(self.data.copy(), ImputeOptions.MEAN)
+ self._run_export_test(imputer)
+
+ def test_export_simple_imputer_median(self):
+ """Test ONNX export for SimpleImputer with 'median' strategy."""
+ _, imputer = impute_nan(self.data.copy(), ImputeOptions.MEDIAN)
+ self._run_export_test(imputer)
+
+ def test_export_simple_imputer_zero(self):
+ """Test ONNX export for SimpleImputer with 'zero' (constant) strategy."""
+ _, imputer = impute_nan(self.data.copy(), ImputeOptions.ZERO)
+ self._run_export_test(imputer)
+
+ def test_export_knn_imputer(self):
+ """Test ONNX export for KNNImputer."""
+ _, imputer = impute_nan(self.data.copy(), ImputeOptions.KNN)
+ self._run_export_test(imputer)
+
+ def test_export_iterative_imputer_raises_error(self):
+ """Test that ONNX export raises an error for IterativeImputer."""
+ _, imputer = impute_nan(self.data.copy(), ImputeOptions.MICE)
+ with self.assertRaises(NotImplementedError):
+ impute_export(imputer, self.n_features)
+
+
+if __name__ == "__main__":
+ unittest.main()
From 2344548ed05605079696bb5d9c18c5b64e323210 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 16:58:40 +0100
Subject: [PATCH 41/50] add check for pca components
---
src/preface/lib/neural.py | 3 ++-
src/preface/lib/svm.py | 5 +++--
src/preface/lib/xgboost.py | 3 ++-
src/preface/train.py | 15 +++++++--------
4 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 3d6cc57..8d549dd 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -80,7 +80,8 @@ def objective(trial) -> float:
x_val, _ = impute_nan(x_val, impute_option)
# reduce dimensionality with PCA
- pca = PCA(n_components=n_components)
+ current_n_components = min(n_components, x_train.shape[0], x_train.shape[1])
+ pca = PCA(n_components=current_n_components)
x_train = pca.fit_transform(x_train)
x_val = pca.transform(x_val)
diff --git a/src/preface/lib/svm.py b/src/preface/lib/svm.py
index dea48a9..8f24871 100644
--- a/src/preface/lib/svm.py
+++ b/src/preface/lib/svm.py
@@ -41,11 +41,12 @@ def objective(trial) -> float:
x_val, _ = impute_nan(x_val, impute_option)
# reduce dimensionality with PCA
- pca = PCA(n_components=n_components)
+ current_n_components = min(n_components, x_train.shape[0], x_train.shape[1])
+ pca = PCA(n_components=current_n_components)
x_train = pca.fit_transform(x_train)
x_val = pca.transform(x_val)
- model.fit(x_train, y_train)
+ model.fit(x_train, y_train.ravel())
preds = model.predict(x_val)
scores.append(mean_squared_error(y_val, preds))
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 39c70e1..0eee6e7 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -52,7 +52,8 @@ def objective(trial) -> float:
x_val, _ = impute_nan(x_val, impute_option)
# Reduce dimensionality with PCA
- pca = PCA(n_components=n_components)
+ current_n_components = min(n_components, x_train.shape[0], x_train.shape[1])
+ pca = PCA(n_components=current_n_components)
x_train = pca.fit_transform(x_train)
x_val = pca.transform(x_val)
diff --git a/src/preface/train.py b/src/preface/train.py
index 62c6f85..474fa9b 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -27,7 +27,6 @@
from preface.lib.svm import svm_tune, svm_fit
from preface.lib.neural import neural_tune, neural_fit
from preface.lib.impute import ImputeOptions, impute_nan
-from preface.lib.ensemble import build_ensemble
# Constants
EXCLUDE_CHRS: list[str] = ["13", "18", "21", "X", "Y"]
@@ -283,13 +282,13 @@ def preface_train(
split_metrics_df.to_csv(out_dir / "training_split_metrics.csv", index=False)
# Build ensemble model from split models
- logging.info("Building ensemble model from split models...")
- build_ensemble(
- split_models,
- x.shape[1],
- out_dir / "PREFACE.onnx",
- metadata={"exclude_chrs": ",".join(exclude_chrs)},
- )
+ # logging.info("Building ensemble model from split models...")
+ # build_ensemble(
+ # split_models,
+ # x.shape[1],
+ # out_dir / "PREFACE.onnx",
+ # metadata={"exclude_chrs": ",".join(exclude_chrs)},
+ # )
# Final evaluation on all training data
logging.info("Evaluating final model on all training data...")
From bf9829da52b98f146e730e8b898efdc25b756f66 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 16:58:50 +0100
Subject: [PATCH 42/50] add test target to makefile
---
Makefile | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 32f3f07..c7dee77 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,39 @@ USERNAME ?= matthdsm
TAG ?= $(shell sed -n 's/^__version__ = "\(.*\)"/\1/p' src/preface/__init__.py)
PLATFORMS ?= linux/amd64
-.PHONY: build push bump-version
+.PHONY: build push bump-version test
+
+TEST_OUTDIR_BASE = test_output
+
+test:
+ @if [ -z "$(SAMPLESHEET)" ]; then echo "Usage: make test SAMPLESHEET="; exit 1; fi
+ @if [ ! -f "$(SAMPLESHEET)" ]; then echo "Error: samplesheet '$(SAMPLESHEET)' not found."; exit 1; fi
+ @rm -rf $(TEST_OUTDIR_BASE)
+ @mkdir -p $(TEST_OUTDIR_BASE)
+
+ @echo "Starting PREFACE train permutation tests..."
+ @for MODEL_TYPE in neural xgboost svm; do \
+ for IMPUTE_TYPE in zero mice mean median knn; do \
+ echo "--- Running $$MODEL_TYPE with $$IMPUTE_TYPE (no tune) ---"; \
+ pixi run PREFACE train \
+ --samplesheet "$(SAMPLESHEET)" \
+ --outdir "$(TEST_OUTDIR_BASE)/$${MODEL_TYPE}_$${IMPUTE_TYPE}_no_tune" \
+ --model $$MODEL_TYPE \
+ --impute $$IMPUTE_TYPE \
+ --nsplits 2 \
+ --nfeat 10; \
+ echo "--- Running $$MODEL_TYPE with $$IMPUTE_TYPE (with tune) ---"; \
+ pixi run PREFACE train \
+ --samplesheet "$(SAMPLESHEET)" \
+ --outdir "$(TEST_OUTDIR_BASE)/$${MODEL_TYPE}_$${IMPUTE_TYPE}_tune" \
+ --model $$MODEL_TYPE \
+ --impute $$IMPUTE_TYPE \
+ --tune \
+ --nsplits 2 \
+ --nfeat 10; \
+ done; \
+ done
+ @echo "All PREFACE train permutation tests completed."
build:
docker build --platform $(PLATFORMS) -t $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) .
From e47eeeb7c5a832f5639bca6e2ce2abeb8a163025 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 17:38:36 +0100
Subject: [PATCH 43/50] small fixes + update readme
---
.gitignore | 1 +
README.md | 21 ++++++++++++++++++---
src/preface/lib/xgboost.py | 2 +-
src/preface/train.py | 33 ++++++++++++++++++++-------------
4 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/.gitignore b/.gitignore
index 514f870..76dd7d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.Rhistory
.R
data/
+test_output/
*.egg-info
__pycache__/
.gemini/
diff --git a/README.md b/README.md
index c13e9a0..3214057 100644
--- a/README.md
+++ b/README.md
@@ -47,22 +47,37 @@ pixi run PREFACE --help
## Model training
+The core of PREFACE is its ability to train a predictive model on your own cohort data.
+
```bash
PREFACE train --samplesheet path/to/samplesheet.tsv [optional arguments]
```
+### Training Process
+
+The training pipeline is a robust, multi-step process designed to build a generalized and accurate model:
+
+1. **Data Loading & Preprocessing**: The tool begins by loading all samples defined in the samplesheet. It checks for data consistency across files and filters out genomic bins (features) that have more than 1% missing values.
+2. **Imputation**: Any remaining missing values (`NaN`) are handled using the strategy specified by the `--impute` option (e.g., filling with the mean, median, using MICE or k-NN).
+3. **Cross-Validation**: To prevent overfitting and get a reliable estimate of performance, PREFACE uses a `GroupShuffleSplit` strategy. It repeatedly splits the data into training and testing sets, ensuring that the distribution of fetal fraction values is similar in each split.
+4. **Dimensionality Reduction**: For each training split, Principal Component Analysis (PCA) is performed to reduce the high-dimensional genomic data into a smaller, more informative set of features (`--nfeat`).
+5. **Model Fitting**: A predictive model is trained on the PCA-reduced data. You can choose between three architectures using the `--model` flag: a `neural` network, `xgboost`, or `svm`.
+6. **Hyperparameter Tuning (Optional)**: If you add the `--tune` flag, PREFACE will first run an optimization process using Optuna to find the best hyperparameters for the chosen model architecture on your specific dataset.
+7. **Ensemble Creation**: Instead of relying on a single model, PREFACE builds an ensemble from all the models trained during the cross-validation splits. This technique typically results in a more robust and accurate final model. The ensemble, including the complete preprocessing pipeline (imputation and PCA), is saved as a single `PREFACE.onnx` file.
+
### Options
| Argument | Type | Default | Function |
| :--- | :--- | :--- | :--- |
| `--samplesheet` | PATH | (Required) | Path to the samplesheet TSV file. |
-| `--outdir` | PATH | `.` | Output directory for models and plots. |
+| `--outdir` | PATH | (Current Dir) | Output directory for models and plots. |
| `--impute` | [zero\|mice\|mean\|median\|knn] | `zero` | Strategy to handle missing values (NaNs). |
| `--exclude-chrs` | TEXT | `13,18,21,X,Y` | Chromosomes to exclude from training features. |
-| `--nfolds` | INTEGER | `5` | Number of folds for cross-validation. |
+| `--nsplits` | INTEGER | `10` | Number of splits for cross-validation. |
| `--nfeat` | INTEGER | `50` | Number of features (PCA components) to use. |
| `--tune` | BOOLEAN | `False` | Enable automatic hyperparameter tuning (via Optuna). |
-| `--model` | [neural\|xgboost] | `neural` | Type of model architecture to train. |
+| `--model` | [neural\|xgboost\|svm] | `neural` | Type of model architecture to train. |
+
## Predicting
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 0eee6e7..100fe92 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -40,7 +40,7 @@ def objective(trial) -> float:
model = XGBRegressor(**params)
# Internal split for the tuner
- gss_internal = GroupShuffleSplit(n_splits=3, test_size=0.2, random_state=42)
+ gss_internal = GroupShuffleSplit(n_splits=5, test_size=0.2, random_state=42)
scores = []
for _, (train_index, test_index) in enumerate(gss_internal.split(x, y, groups)):
diff --git a/src/preface/train.py b/src/preface/train.py
index 474fa9b..66a877f 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -52,7 +52,7 @@ def preface_train(
),
# cross validation options
n_splits: int = typer.Option(
- 50, "--nsplits", help="Number of splits for cross-validation"
+ 10, "--nsplits", help="Number of splits for cross-validation"
),
# PCA options
n_feat: int = typer.Option(
@@ -73,6 +73,11 @@ def preface_train(
start_time: float = time.time()
# Load samplesheet
+ # Check if samplesheet exists
+ if not samplesheet.exists() or not samplesheet.is_file():
+ logging.error(f"Samplesheet file '{samplesheet}' does not exist.")
+ raise typer.Exit(code=1)
+ samplesheet_dir: Path = samplesheet.parent.resolve()
samplesheet_data: pd.DataFrame = pd.read_csv(
samplesheet, comment="#", sep="\t", dtype={"sex": str, "ID": str}
)
@@ -95,15 +100,16 @@ def preface_train(
logging.info(
f"Processing sample {sample['ID']} ({i + 1}/{len(samplesheet_data)})..." # type: ignore
)
+ data_path = samplesheet_dir / Path(sample["filepath"])
if (
- not Path(sample["filepath"]).exists()
- or not Path(sample["filepath"]).is_file() # noqa: W503
+ not data_path.exists()
+ or not data_path.is_file() # noqa: W503
):
- logging.error(f"File '{sample['filepath']}' does not exist.")
+ logging.error(f"File '{data_path}' does not exist.")
raise typer.Exit(code=1)
# load ratios (bed format)
ratios = pd.read_csv(
- sample["filepath"],
+ data_path,
dtype={"chr": str, "start": int, "end": int, "ratio": float},
sep="\t",
header=0,
@@ -141,7 +147,7 @@ def preface_train(
cols_to_drop = missingness[missingness > 0.01].index
if len(cols_to_drop) > 0:
logging.warning(
- f"Dropping {len(cols_to_drop)} bins with more than 1% missing values."
+ f"Dropping {len(cols_to_drop)} regions with more than 1% missing values."
)
ratios_per_sample = ratios_per_sample.drop(columns=cols_to_drop)
@@ -196,7 +202,7 @@ def preface_train(
gss: GroupShuffleSplit = GroupShuffleSplit(
n_splits=n_splits, test_size=0.2, random_state=42
)
- for split, (train_idx, test_idx) in enumerate(gss.split(x, y, groups), 1):
+ for split, (train_idx, test_idx) in enumerate(gss.split(x, y, groups)):
logging.info(f"Processing split {split}/{n_splits}...")
# split into train and test sets
@@ -208,7 +214,8 @@ def preface_train(
x_test, _ = impute_nan(x_test, impute)
# reduce dimensionality with PCA for each split to prevent data leakage
- split_pca = PCA(n_components=n_feat)
+ current_n_feat = min(n_feat, x_train.shape[0], x_train.shape[1])
+ split_pca = PCA(n_components=current_n_feat)
x_train = split_pca.fit_transform(x_train)
x_test = split_pca.transform(x_test)
@@ -268,12 +275,12 @@ def preface_train(
# split number
"split": split,
# regression metrics
- "ff_mae": mean_absolute_error(
- y_test, predictions["regression_predictions"]
+ "mae": mean_absolute_error(
+ y_test, predictions
),
- "ff_r2": r2_score(y_test, predictions["regression_predictions"]),
- "ff_intercept": reg_perf["intercept"],
- "ff_slope": reg_perf["slope"],
+ "r2": r2_score(y_test, predictions),
+ "intercept": reg_perf["intercept"],
+ "slope": reg_perf["slope"],
}
split_metrics.append(metrics)
From 6ad84eabaae9eb5376f804f1b95a47f532fadbed Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 17:44:18 +0100
Subject: [PATCH 44/50] move plotting functions to their own file
---
src/preface/lib/functions.py | 303 +--------------------------------
src/preface/lib/plot.py | 319 +++++++++++++++++++++++++++++++++++
src/preface/train.py | 16 +-
3 files changed, 324 insertions(+), 314 deletions(-)
create mode 100644 src/preface/lib/plot.py
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index eba889a..8eae0d1 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -1,7 +1,3 @@
-from pathlib import Path
-
-import matplotlib.pyplot as plt
-import numpy as np
import numpy.typing as npt
import onnx
import pandas as pd
@@ -9,16 +5,6 @@
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
from sklearn.decomposition import PCA
-from sklearn.linear_model import LinearRegression
-from sklearn.manifold import TSNE
-from sklearn.metrics import (
- mean_absolute_error,
-)
-
-
-COLOR_A: str = "#8DD1C6"
-COLOR_B: str = "#E3C88A"
-COLOR_C: str = "#C87878"
def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.DataFrame:
@@ -47,155 +33,7 @@ def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.Da
return ratios_df
-def plot_regression_performance(
- y_pred: np.ndarray,
- y_true: np.ndarray,
- pca_explained_variance_ratio: np.ndarray,
- n_feat: int,
- xlab: str,
- ylab: str,
- path: Path,
-) -> dict[str, float]:
- """
- Plot performance metrics and return statistics.
- """
- # Ensure 1D arrays
- y_true = np.ravel(y_true)
- y_pred = np.ravel(y_pred)
-
- # Calculate metrics
- mae = mean_absolute_error(y_true, y_pred)
- diff = y_pred - y_true
- sd_diff = float(np.std(diff, ddof=1))
-
- # Linear Regression and Correlation
- if len(np.unique(y_pred)) > 1:
- # Use sklearn LinearRegression
- reg = LinearRegression().fit(y_pred.reshape(-1, 1), y_true)
- intercept = float(reg.intercept_)
- slope = float(reg.coef_[0])
- correlation = float(np.corrcoef(y_true, y_pred)[0, 1])
- else:
- intercept = float(np.mean(y_true))
- slope = 0.0
- correlation = 0.0
-
- # Plotting
- _, axes = plt.subplots(1, 3, figsize=(15, 5))
-
- # Plot 1: PCA Importance
- ax = axes[0]
- y_vals = pca_explained_variance_ratio
- x_vals = np.arange(1, len(y_vals) + 1)
-
- # Filter zeros for log scale
- mask = y_vals > 0
- ax.plot(np.log(x_vals[mask]), np.log(y_vals[mask]), color=COLOR_A, linewidth=2)
- ax.set_xlabel("Principal components (log scale)")
- ax.set_ylabel("Proportion of variance (log scale)")
- ax.set_title("PCA")
-
- # Vertical line at n_feat
- log_n_feat = np.log(n_feat)
- ylim = ax.get_ylim()
- ax.vlines(
- log_n_feat,
- ylim[0],
- ylim[1] * 0.99,
- colors=COLOR_C,
- linestyles="dotted",
- linewidth=3,
- )
- ax.text(
- log_n_feat,
- ylim[1],
- "Number of features",
- color=COLOR_C,
- ha="center",
- va="bottom",
- fontsize=8,
- )
-
- # Plot 2: Scatter Plot
- ax = axes[1]
- mx = max(float(np.max(y_true)), float(np.max(y_pred)))
- ax.scatter(y_pred, y_true, s=10, c="black", alpha=0.6)
- ax.set_xlabel(xlab)
- ax.set_ylabel(ylab)
- ax.set_xlim(0, mx)
- ax.set_ylim(0, mx)
- ax.set_title("Scatter plot")
-
- # Fit line
- if slope != 0:
- fit_line = intercept + slope * np.array([0, mx])
- ax.plot(
- [0, mx],
- fit_line,
- color=COLOR_A,
- linestyle="--",
- linewidth=2,
- label="OLS fit",
- )
- else:
- ax.plot(
- [0, mx],
- [intercept, intercept],
- color=COLOR_A,
- linestyle="--",
- linewidth=2,
- label="Mean fit",
- )
-
- # Identity line
- ax.plot([0, mx], [0, mx], color=COLOR_B, linestyle=":", linewidth=3, label="f(x)=x")
- ax.legend()
- ax.text(0, mx * 1.03, f"(r = {correlation:.3g})", fontsize=9, ha="left")
-
- # Plot 3: Histogram of errors
- ax = axes[2]
- n_bins = max(20, len(y_true) // 10)
- counts, bins, _ = ax.hist(diff, bins=n_bins, density=True, color="black", alpha=0.5)
- ax.set_xlabel(f"{xlab} - {ylab}")
- ax.set_ylabel("Density")
- ax.set_title("Histogram")
-
- mx_hist = float(np.max(counts)) if len(counts) > 0 else 0.1
- ax.vlines(
- mae,
- 0,
- mx_hist,
- colors=COLOR_A,
- linestyles="--",
- linewidth=3,
- label="mean error",
- )
- ax.vlines(0, 0, mx_hist, colors=COLOR_B, linestyles=":", linewidth=3, label="x=0")
- ax.legend()
-
- min_bin = float(min(bins)) if len(bins) > 0 else 0.0
- ax.text(
- min_bin,
- mx_hist * 1.03,
- f"(MAE = {mae:.3g} ± {sd_diff:.3g})",
- fontsize=9,
- ha="left",
- )
-
- plt.tight_layout()
- plt.savefig(path, dpi=300)
- plt.close()
-
- return {
- "intercept": intercept,
- "slope": slope,
- "mae": mae,
- "sd_diff": sd_diff,
- "correlation": correlation,
- }
-
-
-def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
+def fit_rlm(x_values: npt.NDArray, y_values: npt.NDArray) -> tuple[float, float]:
"""
Fit robust linear model (RLM) and return intercept and slope.
"""
@@ -209,145 +47,6 @@ def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
return intercept, slope
-def plot_ffx(
- x_values: np.ndarray,
- y_values: np.ndarray,
- intercept: float,
- slope: float,
- output: Path,
-):
- """
- Plot RLM fit results.
- """
- _, axes = plt.subplots(1, 2, figsize=(10, 5))
- ax = axes[0]
- ax.scatter(x_values, y_values, s=10, c="black", alpha=0.6)
- ax.set_xlabel("FF (%)")
- ax.set_ylabel("μ(ratio X)")
- mx = max(x_values) if len(x_values) > 0 else 1
- ax.set_xlim(0, mx)
- x_range = np.array(
- [
- min(x_values) if len(x_values) > 0 else 0,
- max(x_values) if len(x_values) > 0 else 1,
- ]
- )
- y_range = intercept + slope * x_range
- ax.plot(
- x_range,
- y_range,
- color=COLOR_A,
- linestyle="--",
- linewidth=2,
- label="RLM fit",
- )
- ax.legend()
- ax = axes[1]
- y_values_corrected = (y_values - intercept) / slope if slope != 0 else y_values
- ax.scatter(x_values, y_values_corrected, s=10, c="black", alpha=0.6)
- ax.set_xlabel("FF (%)")
- ax.set_ylabel("FFX (%)")
- ax.set_xlim(0, mx)
- ax.plot(
- [x_range[0], x_range[1]],
- [x_range[0], x_range[1]],
- color=COLOR_B,
- linestyle=":",
- linewidth=3,
- )
- plt.tight_layout()
- plt.savefig(output, dpi=300)
- plt.close()
-
-
-def plot_pca(
- pca: PCA,
- principal_components: npt.NDArray,
- output: Path,
- labels: list | None = None,
- title: str = "PCA Plot",
-) -> None:
- """
- Generate and save a PCA plot.
- """
-
- plt.figure(figsize=(8, 6))
- if labels is not None:
- labels = np.asarray(labels)
- unique_labels = np.unique(labels)
- for label in unique_labels:
- indices = np.where(labels == label)
- plt.scatter(
- principal_components[indices, 0],
- principal_components[indices, 1],
- label=str(label),
- alpha=0.7,
- )
- plt.legend()
- else:
- plt.scatter(
- principal_components[:, 0],
- principal_components[:, 1],
- color=COLOR_A,
- alpha=0.7,
- )
-
- plt.xlabel(f"PC1 ({pca.explained_variance_ratio_[0]:.2%} variance)")
- plt.ylabel(f"PC2 ({pca.explained_variance_ratio_[1]:.2%} variance)")
- plt.title(title)
- plt.tight_layout()
- plt.savefig(output, dpi=300)
- plt.close()
-
-
-def plot_tsne(
- data: np.ndarray | pd.DataFrame,
- output: Path,
- labels: list | None = None,
- perplexity: float = 30.0,
- title: str = "t-SNE Plot",
-) -> None:
- """
- Generate and save a t-SNE plot.
- """
- # t-SNE requires fewer samples than perplexity usually, handled by sklearn but good to know.
- # If samples < perplexity, sklearn warns or adjusts.
- n_samples = data.shape[0]
- eff_perplexity = min(perplexity, n_samples - 1) if n_samples > 1 else 1.0
-
- tsne = TSNE(
- n_components=2,
- perplexity=eff_perplexity,
- random_state=42,
- init="pca",
- learning_rate="auto",
- )
- tsne_results = tsne.fit_transform(data)
-
- plt.figure(figsize=(8, 6))
- if labels is not None:
- labels = np.asarray(labels)
- unique_labels = np.unique(labels)
- for label in unique_labels:
- indices = np.where(labels == label)
- plt.scatter(
- tsne_results[indices, 0],
- tsne_results[indices, 1],
- label=str(label),
- alpha=0.7,
- )
- plt.legend()
- else:
- plt.scatter(tsne_results[:, 0], tsne_results[:, 1], color=COLOR_A, alpha=0.7)
-
- plt.xlabel("t-SNE dimension 1")
- plt.ylabel("t-SNE dimension 2")
- plt.title(title)
- plt.tight_layout()
- plt.savefig(output, dpi=300)
- plt.close()
-
-
def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
"""Export PCA model to ONNX format."""
initial_type = [("input", FloatTensorType([None, input_dim]))]
diff --git a/src/preface/lib/plot.py b/src/preface/lib/plot.py
new file mode 100644
index 0000000..ee1fa90
--- /dev/null
+++ b/src/preface/lib/plot.py
@@ -0,0 +1,319 @@
+from pathlib import Path
+
+import matplotlib.pyplot as plt
+import numpy as np
+import numpy.typing as npt
+import pandas as pd
+import statsmodels.api as sm
+from sklearn.decomposition import PCA
+from sklearn.linear_model import LinearRegression
+from sklearn.manifold import TSNE
+from sklearn.metrics import (
+ mean_absolute_error,
+)
+
+
+COLOR_A: str = "#8DD1C6"
+COLOR_B: str = "#E3C88A"
+COLOR_C: str = "#C87878"
+
+
+def plot_regression_performance(
+ y_pred: np.ndarray,
+ y_true: np.ndarray,
+ pca_explained_variance_ratio: np.ndarray,
+ n_feat: int,
+ xlab: str,
+ ylab: str,
+ path: Path,
+) -> dict[str, float]:
+ """
+ Plot performance metrics and return statistics.
+ """
+ # Ensure 1D arrays
+ y_true = np.ravel(y_true)
+ y_pred = np.ravel(y_pred)
+
+ # Calculate metrics
+ mae = mean_absolute_error(y_true, y_pred)
+ diff = y_pred - y_true
+ sd_diff = float(np.std(diff, ddof=1))
+
+ # Linear Regression and Correlation
+ if len(np.unique(y_pred)) > 1:
+ # Use sklearn LinearRegression
+ reg = LinearRegression().fit(y_pred.reshape(-1, 1), y_true)
+ intercept = float(reg.intercept_)
+ slope = float(reg.coef_[0])
+ correlation = float(np.corrcoef(y_true, y_pred)[0, 1])
+ else:
+ intercept = float(np.mean(y_true))
+ slope = 0.0
+ correlation = 0.0
+
+ # Plotting
+ _, axes = plt.subplots(1, 3, figsize=(15, 5))
+
+ # Plot 1: PCA Importance
+ ax = axes[0]
+ y_vals = pca_explained_variance_ratio
+ x_vals = np.arange(1, len(y_vals) + 1)
+
+ # Filter zeros for log scale
+ mask = y_vals > 0
+ ax.plot(np.log(x_vals[mask]), np.log(y_vals[mask]), color=COLOR_A, linewidth=2)
+ ax.set_xlabel("Principal components (log scale)")
+ ax.set_ylabel("Proportion of variance (log scale)")
+ ax.set_title("PCA")
+
+ # Vertical line at n_feat
+ log_n_feat = np.log(n_feat)
+ ylim = ax.get_ylim()
+ ax.vlines(
+ log_n_feat,
+ ylim[0],
+ ylim[1] * 0.99,
+ colors=COLOR_C,
+ linestyles="dotted",
+ linewidth=3,
+ )
+ ax.text(
+ log_n_feat,
+ ylim[1],
+ "Number of features",
+ color=COLOR_C,
+ ha="center",
+ va="bottom",
+ fontsize=8,
+ )
+
+ # Plot 2: Scatter Plot
+ ax = axes[1]
+ mx = max(float(np.max(y_true)), float(np.max(y_pred)))
+ ax.scatter(y_pred, y_true, s=10, c="black", alpha=0.6)
+ ax.set_xlabel(xlab)
+ ax.set_ylabel(ylab)
+ ax.set_xlim(0, mx)
+ ax.set_ylim(0, mx)
+ ax.set_title("Scatter plot")
+
+ # Fit line
+ if slope != 0:
+ fit_line = intercept + slope * np.array([0, mx])
+ ax.plot(
+ [0, mx],
+ fit_line,
+ color=COLOR_A,
+ linestyle="--",
+ linewidth=2,
+ label="OLS fit",
+ )
+ else:
+ ax.plot(
+ [0, mx],
+ [intercept, intercept],
+ color=COLOR_A,
+ linestyle="--",
+ linewidth=2,
+ label="Mean fit",
+ )
+
+ # Identity line
+ ax.plot([0, mx], [0, mx], color=COLOR_B, linestyle=":", linewidth=3, label="f(x)=x")
+ ax.legend()
+ ax.text(0, mx * 1.03, f"(r = {correlation:.3g})", fontsize=9, ha="left")
+
+ # Plot 3: Histogram of errors
+ ax = axes[2]
+ n_bins = max(20, len(y_true) // 10)
+ counts, bins, _ = ax.hist(diff, bins=n_bins, density=True, color="black", alpha=0.5)
+ ax.set_xlabel(f"{xlab} - {ylab}")
+ ax.set_ylabel("Density")
+ ax.set_title("Histogram")
+
+ mx_hist = float(np.max(counts)) if len(counts) > 0 else 0.1
+ ax.vlines(
+ mae,
+ 0,
+ mx_hist,
+ colors=COLOR_A,
+ linestyles="--",
+ linewidth=3,
+ label="mean error",
+ )
+ ax.vlines(0, 0, mx_hist, colors=COLOR_B, linestyles=":", linewidth=3, label="x=0")
+ ax.legend()
+
+ min_bin = float(min(bins)) if len(bins) > 0 else 0.0
+ ax.text(
+ min_bin,
+ mx_hist * 1.03,
+ f"(MAE = {mae:.3g} ± {sd_diff:.3g})",
+ fontsize=9,
+ ha="left",
+ )
+
+ plt.tight_layout()
+ plt.savefig(path, dpi=300)
+ plt.close()
+
+ return {
+ "intercept": intercept,
+ "slope": slope,
+ "mae": mae,
+ "sd_diff": sd_diff,
+ "correlation": correlation,
+ }
+
+
+def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
+ """
+ Fit robust linear model (RLM) and return intercept and slope.
+ """
+
+ x_rlm = sm.add_constant(x_values)
+ rlm_model = sm.RLM(y_values, x_rlm, M=sm.robust.norms.HuberT())
+ rlm_results = rlm_model.fit()
+ fit_params = rlm_results.params
+ intercept: float = fit_params[0]
+ slope: float = fit_params[1]
+ return intercept, slope
+
+
+def plot_ffx(
+ x_values: np.ndarray,
+ y_values: np.ndarray,
+ intercept: float,
+ slope: float,
+ output: Path,
+):
+ """
+ Plot RLM fit results.
+ """
+ _, axes = plt.subplots(1, 2, figsize=(10, 5))
+ ax = axes[0]
+ ax.scatter(x_values, y_values, s=10, c="black", alpha=0.6)
+ ax.set_xlabel("FF (%)")
+ ax.set_ylabel("μ(ratio X)")
+ mx = max(x_values) if len(x_values) > 0 else 1
+ ax.set_xlim(0, mx)
+ x_range = np.array(
+ [
+ min(x_values) if len(x_values) > 0 else 0,
+ max(x_values) if len(x_values) > 0 else 1,
+ ]
+ )
+ y_range = intercept + slope * x_range
+ ax.plot(
+ x_range,
+ y_range,
+ color=COLOR_A,
+ linestyle="--",
+ linewidth=2,
+ label="RLM fit",
+ )
+ ax.legend()
+ ax = axes[1]
+ y_values_corrected = (y_values - intercept) / slope if slope != 0 else y_values
+ ax.scatter(x_values, y_values_corrected, s=10, c="black", alpha=0.6)
+ ax.set_xlabel("FF (%)")
+ ax.set_ylabel("FFX (%)")
+ ax.set_xlim(0, mx)
+ ax.plot(
+ [x_range[0], x_range[1]],
+ [x_range[0], x_range[1]],
+ color=COLOR_B,
+ linestyle=":",
+ linewidth=3,
+ )
+ plt.tight_layout()
+ plt.savefig(output, dpi=300)
+ plt.close()
+
+
+def plot_pca(
+ pca: PCA,
+ principal_components: npt.NDArray,
+ output: Path,
+ labels: list | None = None,
+ title: str = "PCA Plot",
+) -> None:
+ """
+ Generate and save a PCA plot.
+ """
+
+ plt.figure(figsize=(8, 6))
+ if labels is not None:
+ labels = np.asarray(labels)
+ unique_labels = np.unique(labels)
+ for label in unique_labels:
+ indices = np.where(labels == label)
+ plt.scatter(
+ principal_components[indices, 0],
+ principal_components[indices, 1],
+ label=str(label),
+ alpha=0.7,
+ )
+ plt.legend()
+ else:
+ plt.scatter(
+ principal_components[:, 0],
+ principal_components[:, 1],
+ color=COLOR_A,
+ alpha=0.7,
+ )
+
+ plt.xlabel(f"PC1 ({pca.explained_variance_ratio_[0]:.2%} variance)")
+ plt.ylabel(f"PC2 ({pca.explained_variance_ratio_[1]:.2%} variance)")
+ plt.title(title)
+ plt.tight_layout()
+ plt.savefig(output, dpi=300)
+ plt.close()
+
+
+def plot_tsne(
+ data: np.ndarray | pd.DataFrame,
+ output: Path,
+ labels: list | None = None,
+ perplexity: float = 30.0,
+ title: str = "t-SNE Plot",
+) -> None:
+ """
+ Generate and save a t-SNE plot.
+ """
+ # t-SNE requires fewer samples than perplexity usually, handled by sklearn but good to know.
+ # If samples < perplexity, sklearn warns or adjusts.
+ n_samples = data.shape[0]
+ eff_perplexity = min(perplexity, n_samples - 1) if n_samples > 1 else 1.0
+
+ tsne = TSNE(
+ n_components=2,
+ perplexity=eff_perplexity,
+ random_state=42,
+ init="pca",
+ learning_rate="auto",
+ )
+ tsne_results = tsne.fit_transform(data)
+
+ plt.figure(figsize=(8, 6))
+ if labels is not None:
+ labels = np.asarray(labels)
+ unique_labels = np.unique(labels)
+ for label in unique_labels:
+ indices = np.where(labels == label)
+ plt.scatter(
+ tsne_results[indices, 0],
+ tsne_results[indices, 1],
+ label=str(label),
+ alpha=0.7,
+ )
+ plt.legend()
+ else:
+ plt.scatter(tsne_results[:, 0], tsne_results[:, 1], color=COLOR_A, alpha=0.7)
+
+ plt.xlabel("t-SNE dimension 1")
+ plt.ylabel("t-SNE dimension 2")
+ plt.title(title)
+ plt.tight_layout()
+ plt.savefig(output, dpi=300)
+ plt.close()
diff --git a/src/preface/train.py b/src/preface/train.py
index 66a877f..3243c7c 100755
--- a/src/preface/train.py
+++ b/src/preface/train.py
@@ -16,13 +16,8 @@
from sklearn.metrics import mean_absolute_error, r2_score
from sklearn.model_selection import GroupShuffleSplit
from tensorflow import keras # pylint: disable=no-name-in-module # type: ignore
-
-from preface.lib.functions import (
- plot_regression_performance,
- plot_pca,
- plot_tsne,
- preprocess_ratios,
-)
+from preface.lib.plot import plot_pca, plot_tsne, plot_regression_performance
+from preface.lib.functions import preprocess_ratios
from preface.lib.xgboost import xgboost_tune, xgboost_fit
from preface.lib.svm import svm_tune, svm_fit
from preface.lib.neural import neural_tune, neural_fit
@@ -102,8 +97,7 @@ def preface_train(
)
data_path = samplesheet_dir / Path(sample["filepath"])
if (
- not data_path.exists()
- or not data_path.is_file() # noqa: W503
+ not data_path.exists() or not data_path.is_file() # noqa: W503
):
logging.error(f"File '{data_path}' does not exist.")
raise typer.Exit(code=1)
@@ -275,9 +269,7 @@ def preface_train(
# split number
"split": split,
# regression metrics
- "mae": mean_absolute_error(
- y_test, predictions
- ),
+ "mae": mean_absolute_error(y_test, predictions),
"r2": r2_score(y_test, predictions),
"intercept": reg_perf["intercept"],
"slope": reg_perf["slope"],
From 12b1d0afddd55a18b474408849eb20b326a01558 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 17:53:36 +0100
Subject: [PATCH 45/50] refactor plots, add tests
---
src/preface/lib/functions.py | 22 ++-
src/preface/lib/plot.py | 318 +++++++++++++++++------------------
tests/test_plot.py | 113 +++++++++++++
3 files changed, 286 insertions(+), 167 deletions(-)
create mode 100644 tests/test_plot.py
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index 8eae0d1..c42631d 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -35,16 +35,26 @@ def preprocess_ratios(ratios_df: pd.DataFrame, exclude_chrs: list[str]) -> pd.Da
def fit_rlm(x_values: npt.NDArray, y_values: npt.NDArray) -> tuple[float, float]:
"""
- Fit robust linear model (RLM) and return intercept and slope.
- """
+ Fit a Robust Linear Model (RLM) using Huber's T norm.
+
+ Args:
+ x_values: The independent variables.
+ y_values: The dependent variable.
+ Returns:
+ A tuple containing the intercept and slope of the fitted model.
+ """
+ # Add a constant to the independent variable array for intercept calculation
x_rlm = sm.add_constant(x_values)
+
+ # Fit the RLM model
+ # M=sm.robust.norms.HuberT() specifies the robust norm to use for fitting,
+ # which is less sensitive to outliers than ordinary least squares.
rlm_model = sm.RLM(y_values, x_rlm, M=sm.robust.norms.HuberT())
rlm_results = rlm_model.fit()
- fit_params = rlm_results.params
- intercept: float = fit_params[0]
- slope: float = fit_params[1]
- return intercept, slope
+
+ intercept, slope = rlm_results.params
+ return float(intercept), float(slope)
def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
diff --git a/src/preface/lib/plot.py b/src/preface/lib/plot.py
index ee1fa90..e09db4c 100644
--- a/src/preface/lib/plot.py
+++ b/src/preface/lib/plot.py
@@ -1,47 +1,40 @@
+"""Plotting utilities for PREFACE."""
+
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import numpy.typing as npt
import pandas as pd
-import statsmodels.api as sm
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from sklearn.manifold import TSNE
-from sklearn.metrics import (
- mean_absolute_error,
-)
+from sklearn.metrics import mean_absolute_error
+
+# Define the public API for this module
+__all__ = [
+ "plot_regression_performance",
+ "plot_ffx",
+ "plot_pca",
+ "plot_tsne",
+]
+# Consistent color palette for plots
COLOR_A: str = "#8DD1C6"
COLOR_B: str = "#E3C88A"
COLOR_C: str = "#C87878"
-def plot_regression_performance(
- y_pred: np.ndarray,
- y_true: np.ndarray,
- pca_explained_variance_ratio: np.ndarray,
- n_feat: int,
- xlab: str,
- ylab: str,
- path: Path,
+def _calculate_regression_metrics(
+ y_true: np.ndarray, y_pred: np.ndarray
) -> dict[str, float]:
- """
- Plot performance metrics and return statistics.
- """
- # Ensure 1D arrays
- y_true = np.ravel(y_true)
- y_pred = np.ravel(y_pred)
-
- # Calculate metrics
+ """Calculate regression metrics (MAE, R², slope, intercept)."""
mae = mean_absolute_error(y_true, y_pred)
- diff = y_pred - y_true
- sd_diff = float(np.std(diff, ddof=1))
+ sd_diff = float(np.std(y_pred - y_true, ddof=1))
- # Linear Regression and Correlation
if len(np.unique(y_pred)) > 1:
- # Use sklearn LinearRegression
+ # Reshape y_pred to be a 2D array for LinearRegression
reg = LinearRegression().fit(y_pred.reshape(-1, 1), y_true)
intercept = float(reg.intercept_)
slope = float(reg.coef_[0])
@@ -51,95 +44,99 @@ def plot_regression_performance(
slope = 0.0
correlation = 0.0
- # Plotting
- _, axes = plt.subplots(1, 3, figsize=(15, 5))
+ return {
+ "intercept": intercept,
+ "slope": slope,
+ "mae": mae,
+ "sd_diff": sd_diff,
+ "correlation": correlation,
+ }
+
- # Plot 1: PCA Importance
- ax = axes[0]
+def _plot_pca_importance(
+ ax: plt.Axes, # type: ignore
+ pca_explained_variance_ratio: np.ndarray,
+ n_feat: int,
+) -> None:
+ """Plot the PCA explained variance."""
y_vals = pca_explained_variance_ratio
x_vals = np.arange(1, len(y_vals) + 1)
- # Filter zeros for log scale
+ # Use a mask to plot only non-zero values on a log scale
mask = y_vals > 0
ax.plot(np.log(x_vals[mask]), np.log(y_vals[mask]), color=COLOR_A, linewidth=2)
ax.set_xlabel("Principal components (log scale)")
ax.set_ylabel("Proportion of variance (log scale)")
ax.set_title("PCA")
- # Vertical line at n_feat
+ # Add a vertical line to indicate the number of features used
log_n_feat = np.log(n_feat)
ylim = ax.get_ylim()
ax.vlines(
log_n_feat,
ylim[0],
- ylim[1] * 0.99,
+ ylim[1],
colors=COLOR_C,
linestyles="dotted",
linewidth=3,
)
- ax.text(
- log_n_feat,
- ylim[1],
- "Number of features",
- color=COLOR_C,
- ha="center",
- va="bottom",
- fontsize=8,
- )
+ ax.text(log_n_feat, ylim[1], "n_feat", color=COLOR_C, ha="center", va="bottom")
+
- # Plot 2: Scatter Plot
- ax = axes[1]
- mx = max(float(np.max(y_true)), float(np.max(y_pred)))
+def _plot_scatter(
+ ax: plt.Axes, # type: ignore
+ y_true: np.ndarray,
+ y_pred: np.ndarray,
+ xlab: str,
+ ylab: str,
+ metrics: dict,
+) -> None:
+ """Plot the regression scatter plot with f(x)=x and OLS fit lines."""
+ mx = max(np.max(y_true), np.max(y_pred))
ax.scatter(y_pred, y_true, s=10, c="black", alpha=0.6)
ax.set_xlabel(xlab)
ax.set_ylabel(ylab)
ax.set_xlim(0, mx)
ax.set_ylim(0, mx)
- ax.set_title("Scatter plot")
-
- # Fit line
- if slope != 0:
- fit_line = intercept + slope * np.array([0, mx])
- ax.plot(
- [0, mx],
- fit_line,
- color=COLOR_A,
- linestyle="--",
- linewidth=2,
- label="OLS fit",
- )
- else:
- ax.plot(
- [0, mx],
- [intercept, intercept],
- color=COLOR_A,
- linestyle="--",
- linewidth=2,
- label="Mean fit",
- )
+ ax.set_title("Scatter Plot")
+
+ # Plot Ordinary Least Squares (OLS) fit line
+ fit_line = metrics["intercept"] + metrics["slope"] * np.array([0, mx])
+ ax.plot(
+ [0, mx], fit_line, color=COLOR_A, linestyle="--", linewidth=2, label="OLS fit"
+ )
- # Identity line
+ # Plot identity line for reference
ax.plot([0, mx], [0, mx], color=COLOR_B, linestyle=":", linewidth=3, label="f(x)=x")
ax.legend()
- ax.text(0, mx * 1.03, f"(r = {correlation:.3g})", fontsize=9, ha="left")
+ ax.text(0, mx * 1.03, f"(r = {metrics['correlation']:.3g})", fontsize=9, ha="left")
- # Plot 3: Histogram of errors
- ax = axes[2]
+
+def _plot_error_histogram(
+ ax: plt.Axes, # type: ignore
+ y_true: np.ndarray,
+ y_pred: np.ndarray,
+ xlab: str,
+ ylab: str,
+ metrics: dict,
+) -> None:
+ """Plot the histogram of prediction errors."""
+ diff = y_pred - y_true
n_bins = max(20, len(y_true) // 10)
counts, bins, _ = ax.hist(diff, bins=n_bins, density=True, color="black", alpha=0.5)
ax.set_xlabel(f"{xlab} - {ylab}")
ax.set_ylabel("Density")
- ax.set_title("Histogram")
+ ax.set_title("Error Histogram")
mx_hist = float(np.max(counts)) if len(counts) > 0 else 0.1
ax.vlines(
- mae,
+ metrics["mae"],
0,
mx_hist,
colors=COLOR_A,
linestyles="--",
linewidth=3,
- label="mean error",
+ label="Mean Error",
)
ax.vlines(0, 0, mx_hist, colors=COLOR_B, linestyles=":", linewidth=3, label="x=0")
ax.legend()
@@ -148,36 +145,47 @@ def plot_regression_performance(
ax.text(
min_bin,
mx_hist * 1.03,
- f"(MAE = {mae:.3g} ± {sd_diff:.3g})",
+ f"(MAE = {metrics['mae']:.3g} ± {metrics['sd_diff']:.3g})",
fontsize=9,
ha="left",
)
- plt.tight_layout()
- plt.savefig(path, dpi=300)
- plt.close()
- return {
- "intercept": intercept,
- "slope": slope,
- "mae": mae,
- "sd_diff": sd_diff,
- "correlation": correlation,
- }
-
-
-def fit_rlm(x_values: np.ndarray, y_values: np.ndarray):
+def plot_regression_performance(
+ y_pred: np.ndarray,
+ y_true: np.ndarray,
+ pca_explained_variance_ratio: np.ndarray,
+ n_feat: int,
+ xlab: str,
+ ylab: str,
+ path: Path,
+) -> dict[str, float]:
"""
- Fit robust linear model (RLM) and return intercept and slope.
+ Plot a comprehensive regression performance dashboard and return statistics.
+
+ This function generates a 3-panel plot:
+ 1. PCA explained variance.
+ 2. A scatter plot of predicted vs. true values.
+ 3. A histogram of the prediction errors.
"""
+ y_true_1d = np.ravel(y_true)
+ y_pred_1d = np.ravel(y_pred)
+
+ metrics = _calculate_regression_metrics(y_true_1d, y_pred_1d)
- x_rlm = sm.add_constant(x_values)
- rlm_model = sm.RLM(y_values, x_rlm, M=sm.robust.norms.HuberT())
- rlm_results = rlm_model.fit()
- fit_params = rlm_results.params
- intercept: float = fit_params[0]
- slope: float = fit_params[1]
- return intercept, slope
+ # Create a 3-panel plot
+ # Arguments: nrows, ncols, figsize in inches
+ _, axes = plt.subplots(1, 3, figsize=(15, 5))
+
+ _plot_pca_importance(axes[0], pca_explained_variance_ratio, n_feat)
+ _plot_scatter(axes[1], y_true_1d, y_pred_1d, xlab, ylab, metrics)
+ _plot_error_histogram(axes[2], y_true_1d, y_pred_1d, xlab, ylab, metrics)
+
+ plt.tight_layout()
+ plt.savefig(path, dpi=300)
+ plt.close()
+
+ return metrics
def plot_ffx(
@@ -186,46 +194,38 @@ def plot_ffx(
intercept: float,
slope: float,
output: Path,
-):
+) -> None:
"""
- Plot RLM fit results.
+ Plot FFX (Fetal Fraction from X) vs FF, before and after RLM correction.
"""
_, axes = plt.subplots(1, 2, figsize=(10, 5))
- ax = axes[0]
- ax.scatter(x_values, y_values, s=10, c="black", alpha=0.6)
- ax.set_xlabel("FF (%)")
- ax.set_ylabel("μ(ratio X)")
- mx = max(x_values) if len(x_values) > 0 else 1
- ax.set_xlim(0, mx)
- x_range = np.array(
- [
- min(x_values) if len(x_values) > 0 else 0,
- max(x_values) if len(x_values) > 0 else 1,
- ]
- )
+
+ # Plot 1: Before correction
+ ax1 = axes[0]
+ ax1.scatter(x_values, y_values, s=10, c="black", alpha=0.6)
+ ax1.set_xlabel("FF (%)")
+ ax1.set_ylabel("μ(ratio X)")
+ mx = np.max(x_values) if x_values.size > 0 else 1
+ ax1.set_xlim(0, mx)
+
+ x_range = np.array([0, mx])
y_range = intercept + slope * x_range
- ax.plot(
- x_range,
- y_range,
- color=COLOR_A,
- linestyle="--",
- linewidth=2,
- label="RLM fit",
+ ax1.plot(
+ x_range, y_range, color=COLOR_A, linestyle="--", linewidth=2, label="RLM fit"
)
- ax.legend()
- ax = axes[1]
+ ax1.legend()
+
+ # Plot 2: After correction
+ ax2 = axes[1]
y_values_corrected = (y_values - intercept) / slope if slope != 0 else y_values
- ax.scatter(x_values, y_values_corrected, s=10, c="black", alpha=0.6)
- ax.set_xlabel("FF (%)")
- ax.set_ylabel("FFX (%)")
- ax.set_xlim(0, mx)
- ax.plot(
- [x_range[0], x_range[1]],
- [x_range[0], x_range[1]],
- color=COLOR_B,
- linestyle=":",
- linewidth=3,
+ ax2.scatter(x_values, y_values_corrected, s=10, c="black", alpha=0.6)
+ ax2.set_xlabel("FF (%)")
+ ax2.set_ylabel("FFX (%)")
+ ax2.set_xlim(0, mx)
+ ax2.plot(
+ [0, mx], [0, mx], color=COLOR_B, linestyle=":", linewidth=3, label="f(x)=x"
)
+
plt.tight_layout()
plt.savefig(output, dpi=300)
plt.close()
@@ -235,33 +235,32 @@ def plot_pca(
pca: PCA,
principal_components: npt.NDArray,
output: Path,
- labels: list | None = None,
+ labels: list[str] | None = None,
title: str = "PCA Plot",
) -> None:
- """
- Generate and save a PCA plot.
- """
-
+ """Generate and save a PCA plot, optionally coloring points by labels."""
plt.figure(figsize=(8, 6))
- if labels is not None:
- labels = np.asarray(labels)
- unique_labels = np.unique(labels)
+
+ if labels is None:
+ plt.scatter(
+ principal_components[:, 0],
+ principal_components[:, 1],
+ color=COLOR_A,
+ alpha=0.7,
+ )
+ else:
+ # Use a dictionary for color mapping to ensure consistency if needed,
+ # but for now, rely on matplotlib's default color cycle.
+ unique_labels = sorted(list(set(labels)))
for label in unique_labels:
- indices = np.where(labels == label)
+ indices = [i for i, l in enumerate(labels) if l == label]
plt.scatter(
principal_components[indices, 0],
principal_components[indices, 1],
- label=str(label),
+ label=label,
alpha=0.7,
)
plt.legend()
- else:
- plt.scatter(
- principal_components[:, 0],
- principal_components[:, 1],
- color=COLOR_A,
- alpha=0.7,
- )
plt.xlabel(f"PC1 ({pca.explained_variance_ratio_[0]:.2%} variance)")
plt.ylabel(f"PC2 ({pca.explained_variance_ratio_[1]:.2%} variance)")
@@ -272,19 +271,17 @@ def plot_pca(
def plot_tsne(
- data: np.ndarray | pd.DataFrame,
+ data: npt.NDArray | pd.DataFrame,
output: Path,
- labels: list | None = None,
+ labels: list[str] | None = None,
perplexity: float = 30.0,
title: str = "t-SNE Plot",
) -> None:
- """
- Generate and save a t-SNE plot.
- """
- # t-SNE requires fewer samples than perplexity usually, handled by sklearn but good to know.
- # If samples < perplexity, sklearn warns or adjusts.
+ """Generate and save a t-SNE plot, optionally coloring points by labels."""
n_samples = data.shape[0]
- eff_perplexity = min(perplexity, n_samples - 1) if n_samples > 1 else 1.0
+
+ # Perplexity must be less than the number of samples.
+ eff_perplexity = min(perplexity, n_samples - 1.0) if n_samples > 1 else 1.0
tsne = TSNE(
n_components=2,
@@ -296,23 +293,22 @@ def plot_tsne(
tsne_results = tsne.fit_transform(data)
plt.figure(figsize=(8, 6))
- if labels is not None:
- labels = np.asarray(labels)
- unique_labels = np.unique(labels)
+ if labels is None:
+ plt.scatter(tsne_results[:, 0], tsne_results[:, 1], color=COLOR_A, alpha=0.7)
+ else:
+ unique_labels = sorted(list(set(labels)))
for label in unique_labels:
- indices = np.where(labels == label)
+ indices = [i for i, l in enumerate(labels) if l == label]
plt.scatter(
tsne_results[indices, 0],
tsne_results[indices, 1],
- label=str(label),
+ label=label,
alpha=0.7,
)
plt.legend()
- else:
- plt.scatter(tsne_results[:, 0], tsne_results[:, 1], color=COLOR_A, alpha=0.7)
- plt.xlabel("t-SNE dimension 1")
- plt.ylabel("t-SNE dimension 2")
+ plt.xlabel("t-SNE Dimension 1")
+ plt.ylabel("t-SNE Dimension 2")
plt.title(title)
plt.tight_layout()
plt.savefig(output, dpi=300)
diff --git a/tests/test_plot.py b/tests/test_plot.py
new file mode 100644
index 0000000..214769f
--- /dev/null
+++ b/tests/test_plot.py
@@ -0,0 +1,113 @@
+"""Unit tests for plotting functions."""
+
+import os
+import shutil
+import unittest
+from pathlib import Path
+import numpy as np
+from sklearn.decomposition import PCA
+
+# Import the functions to be tested, including the private one for direct testing
+from preface.lib.plot import (
+ _calculate_regression_metrics,
+ fit_rlm,
+ plot_ffx,
+ plot_pca,
+ plot_regression_performance,
+ plot_tsne,
+)
+
+
+class TestPlottingFunctions(unittest.TestCase):
+ """Test case for the plotting and RLM fitting functions."""
+
+ def setUp(self):
+ """Set up a temporary directory for plot outputs."""
+ self.test_dir = Path("test_plot_outputs")
+ self.test_dir.mkdir(exist_ok=True)
+
+ def tearDown(self):
+ """Remove the temporary directory after tests."""
+ shutil.rmtree(self.test_dir)
+
+ def test_calculate_regression_metrics(self):
+ """Test the private _calculate_regression_metrics function."""
+ y_true = np.array([1, 2, 3, 4, 5])
+ y_pred = np.array([1.1, 2.2, 2.9, 4.3, 5.0])
+ metrics = _calculate_regression_metrics(y_true, y_pred)
+
+ self.assertIn("mae", metrics)
+ self.assertIn("slope", metrics)
+ self.assertIn("intercept", metrics)
+ self.assertIn("correlation", metrics)
+ self.assertAlmostEqual(metrics["mae"], 0.14, places=2)
+ self.assertAlmostEqual(metrics["slope"], 1.0, places=2)
+
+ def test_fit_rlm(self):
+ """Test the fit_rlm function with a clear linear relationship."""
+ x = np.array([1, 2, 3, 4, 5])
+ y = 2 * x + 1 # slope=2, intercept=1
+ intercept, slope = fit_rlm(x, y)
+ self.assertAlmostEqual(intercept, 1.0, places=5)
+ self.assertAlmostEqual(slope, 2.0, places=5)
+
+ def test_plot_regression_performance_smoke(self):
+ """Smoke test for plot_regression_performance."""
+ y_true = np.random.rand(50) * 20
+ y_pred = y_true + np.random.randn(50)
+ pca_variance = np.array([0.5, 0.2, 0.1, 0.05, 0.02])
+ output_path = self.test_dir / "regression_performance.png"
+
+ metrics = plot_regression_performance(
+ y_pred,
+ y_true,
+ pca_variance,
+ n_feat=3,
+ xlab="Predicted",
+ ylab="True",
+ path=output_path,
+ )
+ self.assertTrue(output_path.exists())
+ self.assertIn("mae", metrics)
+
+ def test_plot_ffx_smoke(self):
+ """Smoke test for plot_ffx."""
+ x = np.random.rand(50) * 20
+ y = 0.5 * x + 2 + np.random.randn(50)
+ output_path = self.test_dir / "ffx_plot.png"
+ plot_ffx(x, y, intercept=2.0, slope=0.5, output=output_path)
+ self.assertTrue(output_path.exists())
+
+ def test_plot_pca_smoke(self):
+ """Smoke test for plot_pca."""
+ data = np.random.rand(50, 10)
+ pca = PCA(n_components=2).fit(data)
+ components = pca.transform(data)
+ labels = ["A"] * 25 + ["B"] * 25
+ output_path = self.test_dir / "pca_plot.png"
+
+ # Test with labels
+ plot_pca(pca, components, output_path, labels=labels)
+ self.assertTrue(output_path.exists())
+
+ # Test without labels
+ plot_pca(pca, components, output_path)
+ self.assertTrue(output_path.exists())
+
+ def test_plot_tsne_smoke(self):
+ """Smoke test for plot_tsne."""
+ data = np.random.rand(30, 10) # Perplexity requires n_samples > perplexity
+ labels = ["A"] * 15 + ["B"] * 15
+ output_path = self.test_dir / "tsne_plot.png"
+
+ # Test with labels
+ plot_tsne(data, output_path, labels=labels, perplexity=10)
+ self.assertTrue(output_path.exists())
+
+ # Test without labels
+ plot_tsne(data, output_path, perplexity=10)
+ self.assertTrue(output_path.exists())
+
+
+if __name__ == "__main__":
+ unittest.main()
From 373f1362bc4caceddd7dcdb261192cb9f06f2405 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 19:52:48 +0100
Subject: [PATCH 46/50] add tests
---
pixi.lock | 62 +++---
pyproject.toml | 8 +-
src/preface/lib/ensemble.py | 351 ---------------------------------
src/preface/lib/export_onnx.py | 261 ++++++++++++++++++++++++
src/preface/lib/neural.py | 21 +-
src/preface/lib/svm.py | 6 +-
tests/test_impute.py | 112 +++++++++++
tests/test_neural.py | 155 +++++++++++++++
tests/test_svm.py | 89 +++++++++
9 files changed, 667 insertions(+), 398 deletions(-)
delete mode 100644 src/preface/lib/ensemble.py
create mode 100644 src/preface/lib/export_onnx.py
create mode 100644 tests/test_impute.py
create mode 100644 tests/test_neural.py
create mode 100644 tests/test_svm.py
diff --git a/pixi.lock b/pixi.lock
index 2476d9b..3867d9d 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -93,7 +93,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
@@ -119,11 +119,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
@@ -215,7 +215,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
@@ -241,11 +241,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
@@ -330,7 +330,7 @@ environments:
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
@@ -356,11 +356,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
+ - pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
@@ -2227,10 +2227,10 @@ packages:
- pytest-cov ; extra == 'test'
- scipy ; extra == 'test'
requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
+- pypi: https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
name: pillow
- version: 12.0.0
- sha256: 0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e
+ version: 12.1.0
+ sha256: 6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc
requires_dist:
- furo ; extra == 'docs'
- olefile ; extra == 'docs'
@@ -2259,10 +2259,10 @@ packages:
- trove-classifiers>=2024.10.12 ; extra == 'tests'
- defusedxml ; extra == 'xmp'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
+- pypi: https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
name: pillow
- version: 12.0.0
- sha256: f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344
+ version: 12.1.0
+ sha256: e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c
requires_dist:
- furo ; extra == 'docs'
- olefile ; extra == 'docs'
@@ -2291,10 +2291,10 @@ packages:
- trove-classifiers>=2024.10.12 ; extra == 'tests'
- defusedxml ; extra == 'xmp'
requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl
+- pypi: https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl
name: pillow
- version: 12.0.0
- sha256: 5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b
+ version: 12.1.0
+ sha256: db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac
requires_dist:
- furo ; extra == 'docs'
- olefile ; extra == 'docs'
@@ -2389,16 +2389,16 @@ packages:
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: e632e6e4efa31c951cd37a74b4b3f7d908e7094a73f2fa4658dde0dddf336846
+ sha256: f7f2f9b867798a3ea01c31d73dee363c8dea713fde35f9a0d7c4eec6786c9aa0
requires_dist:
- pandas>=2.3.3,<3
- - numpy>=2.3.5,<3
- - scikit-learn==1.8.0
+ - numpy>=2.4.0,<3
+ - scikit-learn>=1.8.0,<2
- tensorflow>=2.20.0,<3
- matplotlib>=3.10.8,<4
- statsmodels>=0.14.6,<0.15
- - typer>=0.20.0,<0.21
- - rich>=13.0.0,<15
+ - typer>=0.21.0,<0.22
+ - rich>=14.2.0,<15
- xgboost>=3.1.2,<4
- optuna>=4.6.0,<5
- optuna-integration[tfkeras]>=4.6.0,<5
@@ -2409,7 +2409,7 @@ packages:
- skl2onnx>=1.19.1,<2
- onnxconverter-common>=1.16.0,<2
- onnxruntime>=1.23.2,<2
- - tf2onnx>=1.8.4,<2
+ - tf2onnx
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
@@ -3424,10 +3424,10 @@ packages:
- tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
- tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
name: termcolor
- version: 3.2.0
- sha256: a10343879eba4da819353c55cb8049b0933890c2ebf9ad5d3ecd2bb32ea96ea6
+ version: 3.3.0
+ sha256: cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5
requires_dist:
- pytest ; extra == 'tests'
- pytest-cov ; extra == 'tests'
@@ -3524,16 +3524,16 @@ packages:
- requests ; extra == 'telegram'
- ipywidgets>=6 ; extra == 'notebook'
requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/c8/52/1f2df7e7d1be3d65ddc2936d820d4a3d9777a54f4204f5ca46b8513eff77/typer-0.20.1-py3-none-any.whl
+- pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
name: typer
- version: 0.20.1
- sha256: 4b3bde918a67c8e03d861aa02deca90a95bbac572e71b1b9be56ff49affdb5a8
+ version: 0.21.0
+ sha256: c79c01ca6b30af9fd48284058a7056ba0d3bf5cf10d0ff3d0c5b11b68c258ac6
requires_dist:
- click>=8.0.0
- typing-extensions>=3.7.4.3
- shellingham>=1.3.0
- rich>=10.11.0
- requires_python: '>=3.8'
+ requires_python: '>=3.9'
- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
name: typing-extensions
version: 4.15.0
diff --git a/pyproject.toml b/pyproject.toml
index 6a50b2e..19ea103 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -13,13 +13,13 @@ classifiers = [
]
dependencies = [
"pandas>=2.3.3,<3",
- "numpy>=2.3.5,<3",
- "scikit-learn==1.8.0",
+ "numpy>=2.4.0,<3",
+ "scikit-learn>=1.8.0,<2",
"tensorflow>=2.20.0,<3",
"matplotlib>=3.10.8,<4",
"statsmodels>=0.14.6,<0.15",
- "typer>=0.20.0,<0.21",
- "rich>=13.0.0,<15",
+ "typer>=0.21.0,<0.22",
+ "rich>=14.2.0,<15",
"xgboost>=3.1.2,<4",
"optuna>=4.6.0,<5",
"optuna-integration[tfkeras]>=4.6.0,<5",
diff --git a/src/preface/lib/ensemble.py b/src/preface/lib/ensemble.py
deleted file mode 100644
index fad3b6f..0000000
--- a/src/preface/lib/ensemble.py
+++ /dev/null
@@ -1,351 +0,0 @@
-from pathlib import Path
-
-import numpy as np
-import onnx
-import onnxmltools
-import tensorflow as tf
-import tf2onnx
-from onnx import TensorProto, helper
-from onnx.compose import add_prefix, merge_models
-from skl2onnx import convert_sklearn
-from skl2onnx.common.data_types import FloatTensorType
-from sklearn.decomposition import PCA
-from sklearn.svm import SVR, SVC
-from tensorflow.keras import Model # type: ignore
-from xgboost import XGBRegressor
-
-
-def _ensure_opset(model_proto, version=12):
- """
- Force the default domain opset to a specific version.
- skl2onnx sometimes produces older opsets (e.g. 9) even when 12 is requested.
- """
- for op in model_proto.opset_import:
- if (not op.domain or op.domain == "ai.onnx") and op.version < version:
- op.version = version
- return model_proto
-
-
-def build_ensemble(
- models: list[tuple[object, PCA, Model | XGBRegressor | dict[str, SVR | SVC]]],
- input_dim: int,
- output_path: Path,
- metadata: dict[str, str] | None = None,
-) -> None:
- """
- Save an ensemble of models (Imputer + PCA + Model) combined.
- models: List of (Imputer, PCA, Model) tuples.
- metadata: Optional dictionary of metadata to save in the ONNX model.
- """
-
- prefixed_models = []
- fold_info = [] # Store (model_type, reg_base, class_base) for each fold
-
- # Process each fold
- for i, (imputer, pca, model) in enumerate(models):
- fold_prefix = f"fold_{i}_"
-
- # Convert Imputer
- initial_type = [("input", FloatTensorType([None, input_dim]))]
-
- # sklearn imputer
- imputer_onnx = convert_sklearn(
- imputer, initial_types=initial_type, target_opset=12
- )
- _ensure_opset(imputer_onnx, 12)
-
- # Prefix Imputer
- imputer_onnx = add_prefix(imputer_onnx, prefix="imputer_") # type: ignore
- imputer_out_name = imputer_onnx.graph.output[0].name # type: ignore
-
- # Convert PCA
- # Imputer -> PCA
- # Use pca.n_features_in_ to handle case where imputer reduced dimensions
- n_features_pca = getattr(pca, "n_features_in_", input_dim)
- pca_initial_type = [("input_pca", FloatTensorType([None, n_features_pca]))]
- pca_onnx = convert_sklearn(pca, initial_types=pca_initial_type, target_opset=12)
- _ensure_opset(pca_onnx, 12)
-
- # Prefix PCA
- pca_onnx = add_prefix(pca_onnx, prefix="pca_") # type: ignore
- pca_in_name = pca_onnx.graph.input[0].name # type: ignore
- pca_out_name = pca_onnx.graph.output[0].name # type: ignore
-
- # Merge Imputer + PCA
- current_model = merge_models(
- imputer_onnx, # type: ignore
- pca_onnx, # type: ignore
- io_map=[(imputer_out_name, pca_in_name)], # type: ignore
- )
- # Update output name
- current_out_name = pca_out_name
-
- # 3. Convert Model
- # Input to Model is PCA output. Shape: [None, n_components]
- n_comps = pca.n_components_
-
- model_type = "unknown"
- if isinstance(model, Model):
- model_type = "nn"
- elif isinstance(model, (dict, list, tuple)): # Handle dict for SVM
- model_type = "svm"
- else:
- model_type = "xgb"
-
- if model_type == "nn":
- spec = (tf.TensorSpec((None, n_comps), tf.float32, name="input_model"),) # type: ignore
- m_onnx, _ = tf2onnx.convert.from_keras(
- model, input_signature=spec, opset=12
- )
- m_onnx.graph.name = f"fold_{i}_model"
-
- # Prefix NN
- m_onnx = add_prefix(m_onnx, prefix="nn_")
- m_in_name = m_onnx.graph.input[0].name
-
- # Merge (Imputer+PCA) + Model
- current_model = merge_models(
- current_model, # type: ignore
- m_onnx,
- io_map=[(current_out_name, m_in_name)], # type: ignore
- )
-
- # Record outputs
- # Assuming standard naming for NN for now as we can't easily inspect without graph structure knowledge
- fold_info.append(("nn", "nn_reg_output", "nn_class_output"))
-
- elif model_type == "xgb":
- m_onnx = onnxmltools.convert_xgboost(
- model,
- initial_types=[("input_model", FloatTensorType([None, n_comps]))],
- target_opset=12,
- )
-
- # Prefix XGB
- m_onnx = add_prefix(m_onnx, prefix="xgb_")
- m_in_name = m_onnx.graph.input[0].name
-
- # Capture output name
- xgb_out_base = m_onnx.graph.output[0].name
-
- # Merge (Imputer+PCA) + Model
- current_model = merge_models(
- current_model, # type: ignore
- m_onnx,
- io_map=[(current_out_name, m_in_name)], # type: ignore
- )
-
- fold_info.append(("xgb", xgb_out_base, None))
-
- elif model_type == "svm":
- # Expecting dict with 'SVR' and 'SVC'
- svr = model["SVR"]
- svc = model["SVC"]
-
- # Patch SVR if no support vectors (e.g. large epsilon)
- if hasattr(svr, "support_vectors_") and svr.support_vectors_.shape[0] == 0:
- # Add dummy support vector with 0 weight
- dummy_sv = np.zeros(
- (1, svr.support_vectors_.shape[1]), dtype=np.float32
- )
- svr.support_vectors_ = dummy_sv
-
- # Patch internal attributes used by coef_ property
- svr._dual_coef_ = np.zeros((1, 1), dtype=np.float32)
- svr.dual_coef_ = svr._dual_coef_
-
- if hasattr(svr, "_n_support"):
- svr._n_support = np.array([1], dtype=np.int32)
-
- # Convert SVR
- svr_onnx = convert_sklearn(
- svr,
- initial_types=[("input_svr", FloatTensorType([None, n_comps]))],
- target_opset=12,
- )
- _ensure_opset(svr_onnx, 12)
-
- # Prefix SVR
- svr_onnx = add_prefix(svr_onnx, prefix="svr_")
- svr_in_name = svr_onnx.graph.input[0].name
- svr_out_base = svr_onnx.graph.output[0].name
-
- # Convert SVC
- # zipmap=False is important to get probabilities as tensor
- svc_onnx = convert_sklearn(
- svc,
- initial_types=[("input_svc", FloatTensorType([None, n_comps]))],
- target_opset=12,
- options={"zipmap": False},
- )
- _ensure_opset(svc_onnx, 12)
-
- # Prefix SVC
- svc_onnx = add_prefix(svc_onnx, prefix="svc_")
- svc_in_name = svc_onnx.graph.input[0].name
- # Output 0 is label, Output 1 is probabilities (usually)
- svc_out_base = svc_onnx.graph.output[1].name
-
- # Combine SVR and SVC into one model (parallel branches)
- svm_combined = merge_models(svr_onnx, svc_onnx, io_map=[])
-
- # Merge (Imputer+PCA) with (SVR+SVC)
- # Connect PCA output to both SVR and SVC inputs
- current_model = merge_models(
- current_model,
- svm_combined,
- io_map=[
- (current_out_name, svr_in_name),
- (current_out_name, svc_in_name),
- ],
- )
-
- fold_info.append(("svm", svr_out_base, svc_out_base))
-
- # Prefix everything in this fold's graph
- prefixed_model = add_prefix(current_model, prefix=fold_prefix)
- prefixed_models.append(prefixed_model)
-
- # --- Merge All Folds ---
- # We want a single input "input" that feeds into all fold_i_input
-
- # Start with the first fold
- combined_model = prefixed_models[0]
-
- for i in range(1, len(prefixed_models)):
- combined_model = merge_models(
- combined_model,
- prefixed_models[i],
- io_map=[],
- )
-
- graph = combined_model.graph
-
- # Find all inputs that look like "fold_X_input" or "fold_X_input_pca"
- fold_inputs = []
- for node in graph.input:
- if node.name.endswith("input") or node.name.endswith("input_pca"):
- fold_inputs.append(node.name)
-
- # Create a global input
- global_input_name = "input"
-
- # Replace all usages of "fold_i_input" with "global_input".
- for node in graph.node:
- for idx, input_name in enumerate(node.input):
- if input_name in fold_inputs:
- node.input[idx] = global_input_name
-
- # Reset graph inputs
- while len(graph.input) > 0:
- graph.input.pop()
-
- graph.input.extend(
- [
- helper.make_tensor_value_info(
- global_input_name,
- FloatTensorType([None, input_dim]).to_onnx_type().tensor_type.elem_type,
- [None, input_dim],
- )
- ]
- )
-
- # --- Average Outputs ---
- reg_names = []
- class_names = []
-
- # Helper to find output names
- for i, (model_type, reg_base, class_base) in enumerate(fold_info):
- prefix = f"fold_{i}_"
-
- if model_type == "nn":
- # Keras outputs are typically named by layer names.
- # We added "nn_" prefix.
- reg_names.append(prefix + reg_base)
- class_names.append(prefix + class_base)
-
- elif model_type == "xgb":
- # XGBoost output "variable" -> "xgb_variable"
- xgb_out = prefix + reg_base
-
- # We need to split this output. It is [Batch, 2].
- # Column 0: Reg, Column 1: Class (Prob)
-
- split_reg = f"{prefix}reg_split"
- split_class = f"{prefix}class_split"
-
- split_node = helper.make_node(
- "Split",
- inputs=[xgb_out],
- outputs=[split_reg, split_class],
- name=f"{prefix}Split",
- axis=1,
- split=[1, 1],
- )
- graph.node.append(split_node)
-
- reg_names.append(split_reg)
- class_names.append(split_class)
-
- elif model_type == "svm":
- # SVR output "variable" -> "svr_variable"
- # SVC output "output_probability" -> "svc_output_probability"
-
- svm_reg_out = prefix + reg_base
- svm_class_prob_out = prefix + class_base
-
- reg_names.append(svm_reg_out)
-
- # SVC probability output is [Batch, 2] (prob class 0, prob class 1).
- # We need to extract the second column (class 1).
-
- svm_class_split = f"{prefix}class_prob_split"
- svm_class_0_dummy = f"{prefix}class_prob_0_dummy"
-
- split_node_svm = helper.make_node(
- "Split",
- inputs=[svm_class_prob_out],
- outputs=[svm_class_0_dummy, svm_class_split],
- name=f"{prefix}SVMSplit",
- axis=1,
- split=[1, 1],
- )
- graph.node.append(split_node_svm)
-
- class_names.append(svm_class_split)
-
- # Add Mean nodes
- final_reg_name = "final_ff_score"
- final_class_name = "final_sex_prob"
-
- mean_reg_node = helper.make_node(
- "Mean", inputs=reg_names, outputs=[final_reg_name], name="Mean_FF"
- )
- mean_class_node = helper.make_node(
- "Mean", inputs=class_names, outputs=[final_class_name], name="Mean_Sex"
- )
-
- graph.node.extend([mean_reg_node, mean_class_node])
-
- # Clean outputs
- while len(graph.output) > 0:
- graph.output.pop()
-
- graph.output.extend(
- [
- helper.make_tensor_value_info(final_reg_name, TensorProto.FLOAT, [None, 1]),
- helper.make_tensor_value_info(
- final_class_name, TensorProto.FLOAT, [None, 1]
- ),
- ]
- )
-
- # Add metadata
- if metadata:
- for key, value in metadata.items():
- meta = combined_model.metadata_props.add()
- meta.key = key
- meta.value = value
-
- onnx.save(combined_model, output_path)
- print(f"Ensemble saved to {output_path}")
diff --git a/src/preface/lib/export_onnx.py b/src/preface/lib/export_onnx.py
new file mode 100644
index 0000000..060906d
--- /dev/null
+++ b/src/preface/lib/export_onnx.py
@@ -0,0 +1,261 @@
+from pathlib import Path
+from typing import List, Tuple, Dict
+
+import onnx
+from onnx import TensorProto, helper
+from onnx.compose import add_prefix, merge_models
+from skl2onnx import convert_sklearn
+from skl2onnx.common.data_types import FloatTensorType
+from sklearn.impute import SimpleImputer, KNNImputer, IterativeImputer
+from sklearn.decomposition import PCA
+from sklearn.svm import SVR
+from tensorflow.keras import Model # type: ignore
+from xgboost import XGBRegressor
+
+
+def _ensure_opset(model_proto: onnx.ModelProto, version: int = 18) -> onnx.ModelProto:
+ """
+ Force the default domain opset to a specific version.
+ """
+ for op in model_proto.opset_import:
+ if (not op.domain or op.domain == "ai.onnx") and op.version < version:
+ op.version = version
+ return model_proto
+
+
+def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
+ """
+ Convert a PCA model to ONNX format.
+ """
+ pca_initial_type = [("pca_input", FloatTensorType([None, input_dim]))]
+ pca_onnx = convert_sklearn(
+ pca,
+ initial_types=pca_initial_type,
+ target_opset=18,
+ )
+ _ensure_opset(pca_onnx, 18) # type: ignore
+
+ return pca_onnx # type: ignore
+
+
+def export_ensemble(
+ models: List[
+ Tuple[
+ SimpleImputer | KNNImputer | IterativeImputer,
+ PCA,
+ Model | XGBRegressor | SVR,
+ ]
+ ],
+ input_dim: int,
+ output_path: Path,
+ metadata: Dict[str, str] | None = None,
+) -> None:
+ """
+ Save an ensemble of models (Imputer + PCA + Model) combined.
+ models: List of (Imputer, PCA, Model) tuples.
+ metadata: Optional dictionary of metadata to save in the ONNX model.
+ """
+
+ prefixed_models = []
+ split_info = [] # Store (model_type, reg_base, class_base) for each split
+
+ # Process each split
+ for i, (imputer, pca, model) in enumerate(models):
+ split_prefix = f"split_{i}_"
+
+ # 1. Convert Imputer
+ initial_type = [("input", FloatTensorType([None, input_dim]))]
+ imputer_onnx = convert_sklearn(
+ imputer, initial_types=initial_type, target_opset={"": 12, "ai.onnx.ml": 2}
+ )
+ _ensure_opset(imputer_onnx, 12) # type: ignore
+
+ # Prefix Imputer
+ imputer_onnx = add_prefix(imputer_onnx, prefix="imputer_") # type: ignore
+ imputer_out_name = imputer_onnx.graph.output[0].name # type: ignore
+
+ # 2. Convert PCA
+ pca_onnx = pca_to_onnx(pca, input_dim)
+ pca_in_name = pca_onnx.graph.input[0].name # type: ignore
+ pca_out_name = pca_onnx.graph.output[0].name # type: ignore
+
+ # Merge Imputer + PCA
+ current_model = merge_models(
+ imputer_onnx, # type: ignore
+ pca_onnx, # type: ignore
+ io_map=[(imputer_out_name, pca_in_name)], # type: ignore
+ )
+ current_out_name = pca_out_name
+ n_comps = pca.n_components_
+
+ # 3. Convert Model
+ model_type = "unknown"
+ if isinstance(model, Model):
+ model_type = "nn"
+ current_model, info = export_nn(
+ model, n_comps, current_model, current_out_name, i
+ )
+ split_info.extend(info)
+
+ elif isinstance(model, SVR):
+ current_model, info = export_svm(
+ model, n_comps, current_model, current_out_name
+ )
+ split_info.extend(info)
+
+ elif isinstance(model, XGBRegressor):
+ model_type = "xgb"
+ current_model, info = export_xgb(
+ model, n_comps, current_model, current_out_name
+ )
+ split_info.extend(info)
+
+ # Prefix everything in this split's graph
+ prefixed_model = add_prefix(current_model, prefix=split_prefix)
+ prefixed_models.append(prefixed_model)
+
+ # --- Merge All splits ---
+ # We want a single input "input" that feeds into all split_i_input
+
+ # Start with the first split
+ combined_model = prefixed_models[0]
+
+ for i in range(1, len(prefixed_models)):
+ combined_model = merge_models(
+ combined_model,
+ prefixed_models[i],
+ io_map=[],
+ )
+
+ graph = combined_model.graph
+
+ # Find all inputs that look like "split_X_imputer_input"
+ # Because we added "imputer_" prefix inside the loop, and then "split_i_" prefix outside.
+ # The input name structure is likely "split_i_imputer_input"
+
+ # We need to find the specific input names created by add_prefix
+ # We'll look for any input ending with "imputer_input"
+ split_inputs = []
+ for node in graph.input:
+ if node.name.endswith("imputer_input"):
+ split_inputs.append(node.name)
+
+ # Create a global input
+ global_input_name = "input"
+
+ # Replace all usages of split inputs with global input
+ for node in graph.node:
+ for idx, input_name in enumerate(node.input):
+ if input_name in split_inputs:
+ node.input[idx] = global_input_name
+
+ # Reset graph inputs to just the global input
+ while len(graph.input) > 0:
+ graph.input.pop()
+
+ graph.input.extend(
+ [
+ helper.make_tensor_value_info(
+ global_input_name,
+ FloatTensorType([None, input_dim]).to_onnx_type().tensor_type.elem_type,
+ [None, input_dim],
+ )
+ ]
+ )
+
+ # --- Average Outputs ---
+ reg_names = []
+ class_names = []
+
+ # Helper to find output names
+ for i, (model_type, reg_base, class_base) in enumerate(split_info):
+ prefix = f"split_{i}_"
+
+ if model_type == "nn":
+ reg_names.append(prefix + reg_base)
+ if class_base:
+ class_names.append(prefix + class_base)
+
+ elif model_type == "xgb":
+ # XGBoost output [Batch, 2] -> Col 0: Reg, Col 1: Class (Prob)
+ xgb_out = prefix + reg_base
+ split_reg = f"{prefix}reg_split"
+ split_class = f"{prefix}class_split"
+
+ split_node = helper.make_node(
+ "Split",
+ inputs=[xgb_out],
+ outputs=[split_reg, split_class],
+ name=f"{prefix}Split",
+ axis=1,
+ split=[1, 1],
+ )
+ graph.node.append(split_node)
+
+ reg_names.append(split_reg)
+ class_names.append(split_class)
+
+ elif model_type == "svm":
+ reg_names.append(prefix + reg_base)
+
+ # SVC prob output [Batch, 2] -> want col 1
+ svm_class_prob_out = prefix + class_base
+ svm_class_split = f"{prefix}class_prob_split"
+ svm_class_0_dummy = f"{prefix}class_prob_0_dummy"
+
+ split_node_svm = helper.make_node(
+ "Split",
+ inputs=[svm_class_prob_out],
+ outputs=[svm_class_0_dummy, svm_class_split],
+ name=f"{prefix}SVMSplit",
+ axis=1,
+ split=[1, 1],
+ )
+ graph.node.append(split_node_svm)
+
+ class_names.append(svm_class_split)
+
+ # Add Mean nodes
+ final_reg_name = "final_ff_score"
+ final_class_name = "final_sex_prob"
+
+ # Check if we have outputs to average
+ if reg_names:
+ mean_reg_node = helper.make_node(
+ "Mean", inputs=reg_names, outputs=[final_reg_name], name="Mean_FF"
+ )
+ graph.node.append(mean_reg_node)
+
+ if class_names:
+ mean_class_node = helper.make_node(
+ "Mean", inputs=class_names, outputs=[final_class_name], name="Mean_Sex"
+ )
+ graph.node.append(mean_class_node)
+
+ # Clean outputs
+ while len(graph.output) > 0:
+ graph.output.pop()
+
+ new_outputs = []
+ if reg_names:
+ new_outputs.append(
+ helper.make_tensor_value_info(final_reg_name, TensorProto.FLOAT, [None, 1])
+ )
+ if class_names:
+ new_outputs.append(
+ helper.make_tensor_value_info(
+ final_class_name, TensorProto.FLOAT, [None, 1]
+ )
+ )
+
+ graph.output.extend(new_outputs)
+
+ # Add metadata
+ if metadata:
+ for key, value in metadata.items():
+ meta = combined_model.metadata_props.add()
+ meta.key = key
+ meta.value = value
+
+ onnx.save(combined_model, output_path)
+ print(f"Ensemble saved to {output_path}")
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 8d549dd..e38d635 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -49,6 +49,7 @@ def neural_tune(
n_components: int,
outdir: Path,
impute_option: ImputeOptions,
+ n_trials: int = 30,
) -> dict:
def objective(trial) -> float:
params = {
@@ -59,14 +60,6 @@ def objective(trial) -> float:
"epochs": trial.suggest_int("epochs", 20, 100, step=10),
"batch_size": trial.suggest_int("batch_size", 8, 64, step=8),
}
- model = create_model(
- input_dim=x.shape[1],
- n_layers=params["n_layers"],
- hidden_size=params["hidden_size"],
- learning_rate=params["learning_rate"],
- dropout_rate=params["dropout_rate"],
- )
-
# Internal split for the tuner
gss_internal = GroupShuffleSplit(n_splits=5, test_size=0.2, random_state=42)
scores = []
@@ -85,6 +78,14 @@ def objective(trial) -> float:
x_train = pca.fit_transform(x_train)
x_val = pca.transform(x_val)
+ model = create_model(
+ input_dim=current_n_components,
+ n_layers=params["n_layers"],
+ hidden_size=params["hidden_size"],
+ learning_rate=params["learning_rate"],
+ dropout_rate=params["dropout_rate"],
+ )
+
history = model.fit(
x_train,
y_train,
@@ -102,7 +103,7 @@ def objective(trial) -> float:
study = optuna.create_study(
direction="minimize", pruner=optuna.pruners.MedianPruner()
)
- study.optimize(objective, n_trials=30)
+ study.optimize(objective, n_trials=n_trials)
fig = optuna.visualization.plot_optimization_history(study)
fig.write_image(outdir / "neural_tuning_history.png")
@@ -158,6 +159,6 @@ def neural_export(model: Model) -> onnx.ModelProto:
"""Export neural network to ONNX format."""
initial_type = [("neural_input", FloatTensorType([None, model.input_shape[1]]))]
onnx_model = onnxmltools.convert_keras(
- model, initial_types=initial_type, target_opset=18
+ model, initial_types=initial_type, target_opset=13
)
return onnx_model
diff --git a/src/preface/lib/svm.py b/src/preface/lib/svm.py
index 8f24871..8d64521 100644
--- a/src/preface/lib/svm.py
+++ b/src/preface/lib/svm.py
@@ -6,6 +6,7 @@
from sklearn.svm import SVR
from sklearn.model_selection import GroupShuffleSplit
from sklearn.decomposition import PCA
+from sklearn.experimental import enable_iterative_imputer # type: ignore # noqa
import optuna
import onnxmltools
import onnx
@@ -19,6 +20,7 @@ def svm_tune(
n_components: int, # number of PCA components
outdir: Path, # output directory
impute_option: ImputeOptions, # imputation strategy
+ n_trials: int = 30, # number of optimization trials
) -> dict:
def objective(trial) -> float:
params = {
@@ -56,7 +58,7 @@ def objective(trial) -> float:
study = optuna.create_study(
direction="minimize", pruner=optuna.pruners.MedianPruner()
)
- study.optimize(objective, n_trials=30)
+ study.optimize(objective, n_trials=n_trials)
fig = optuna.visualization.plot_optimization_history(study)
fig.write_image(outdir / "svm_tuning_history.png")
@@ -87,6 +89,6 @@ def svm_export(model: SVR) -> onnx.ModelProto:
"""Export SVM model to ONNX format."""
initial_type = [("svm_input", FloatTensorType([None, model.n_features_in_]))]
onnx_model = onnxmltools.convert_sklearn(
- model, initial_types=initial_type, target_opset=18
+ model, initial_types=initial_type, target_opset=15
)
return onnx_model # type: ignore
diff --git a/tests/test_impute.py b/tests/test_impute.py
new file mode 100644
index 0000000..0dad485
--- /dev/null
+++ b/tests/test_impute.py
@@ -0,0 +1,112 @@
+import unittest
+import numpy as np
+from sklearn.experimental import enable_iterative_imputer # noqa: F401
+from sklearn.impute import IterativeImputer, KNNImputer, SimpleImputer
+from preface.lib.impute import impute_nan, ImputeOptions
+
+
+class TestImpute(unittest.TestCase):
+ def setUp(self):
+ # Create a simple dataset with known properties
+ # shape (5, 3)
+ self.data = np.array(
+ [
+ [1.0, 2.0, 3.0],
+ [4.0, 5.0, 6.0],
+ [7.0, 8.0, 9.0],
+ [10.0, 11.0, 12.0],
+ [np.nan, np.nan, np.nan],
+ ]
+ )
+ # Add some NaNs in other places
+ self.data[0, 0] = np.nan # was 1.0
+ self.data[2, 1] = np.nan # was 8.0
+
+ # Create a version with columns that have clear means/medians
+ # Col 0: [?, 4, 7, 10, ?] -> valid: 4, 7, 10. Mean=7, Median=7
+ # Col 1: [2, 5, ?, 11, ?] -> valid: 2, 5, 11. Mean=6, Median=5
+ # Col 2: [3, 6, 9, 12, ?] -> valid: 3, 6, 9, 12. Mean=7.5, Median=7.5
+
+ # Refined data for checking values
+ self.data_check = np.array(
+ [
+ [np.nan, 2.0, 3.0],
+ [4.0, 5.0, 6.0],
+ [7.0, np.nan, 9.0],
+ [10.0, 11.0, 12.0],
+ [np.nan, np.nan, np.nan],
+ ]
+ )
+
+ # NOTE: SimpleImputer with default axis=0 (columns)
+ # Col 0 valid: 4, 7, 10 -> Mean: 7.0, Median: 7.0
+ # Col 1 valid: 2, 5, 11 -> Mean: 6.0, Median: 5.0
+ # Col 2 valid: 3, 6, 9, 12 -> Mean: 7.5, Median: 7.5 (avg of 6 and 9)
+ # Note: Median of [3,6,9,12] is (6+9)/2 = 7.5
+
+ def test_impute_zero(self):
+ """Test ZERO imputation."""
+ imputed_data, imputer = impute_nan(self.data_check.copy(), ImputeOptions.ZERO)
+
+ self.assertIsInstance(imputer, SimpleImputer)
+ self.assertFalse(np.isnan(imputed_data).any())
+
+ # Check specific values were replaced by 0
+ self.assertEqual(imputed_data[0, 0], 0.0)
+ self.assertEqual(imputed_data[2, 1], 0.0)
+ self.assertEqual(imputed_data[4, 0], 0.0)
+
+ # Check non-NaN values are preserved
+ self.assertEqual(imputed_data[1, 0], 4.0)
+
+ def test_impute_mean(self):
+ """Test MEAN imputation."""
+ imputed_data, imputer = impute_nan(self.data_check.copy(), ImputeOptions.MEAN)
+
+ self.assertIsInstance(imputer, SimpleImputer)
+ self.assertFalse(np.isnan(imputed_data).any())
+
+ # Col 0 mean is 7.0
+ self.assertAlmostEqual(imputed_data[0, 0], 7.0)
+ # Col 1 mean is 6.0
+ self.assertAlmostEqual(imputed_data[2, 1], 6.0)
+
+ def test_impute_median(self):
+ """Test MEDIAN imputation."""
+ imputed_data, imputer = impute_nan(self.data_check.copy(), ImputeOptions.MEDIAN)
+
+ self.assertIsInstance(imputer, SimpleImputer)
+ self.assertFalse(np.isnan(imputed_data).any())
+
+ # Col 0 median is 7.0
+ self.assertAlmostEqual(imputed_data[0, 0], 7.0)
+ # Col 1 median is 5.0
+ self.assertAlmostEqual(imputed_data[2, 1], 5.0)
+
+ def test_impute_knn(self):
+ """Test KNN imputation."""
+ # Need enough samples for neighbors, defaulting to 5 in implementation
+ # But our data is small (5 rows). KNNImputer(n_neighbors=5) might be capped by samples.
+ # The implementation uses default n_neighbors=5.
+ # With 5 samples, it will use available neighbors.
+
+ imputed_data, imputer = impute_nan(self.data_check.copy(), ImputeOptions.KNN)
+
+ self.assertIsInstance(imputer, KNNImputer)
+ self.assertFalse(np.isnan(imputed_data).any())
+ self.assertEqual(imputed_data.shape, self.data_check.shape)
+
+ def test_impute_mice(self):
+ """Test MICE imputation."""
+ # Suppress logging for clean test output or check it if needed
+ # Just checking it runs and returns IterativeImputer
+
+ imputed_data, imputer = impute_nan(self.data_check.copy(), ImputeOptions.MICE)
+
+ self.assertIsInstance(imputer, IterativeImputer)
+ self.assertFalse(np.isnan(imputed_data).any())
+ self.assertEqual(imputed_data.shape, self.data_check.shape)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_neural.py b/tests/test_neural.py
new file mode 100644
index 0000000..d7c20b2
--- /dev/null
+++ b/tests/test_neural.py
@@ -0,0 +1,155 @@
+import unittest
+import shutil
+import tempfile
+import numpy as np
+import logging
+from pathlib import Path
+from tensorflow.keras import Model
+import onnx
+from preface.lib.neural import create_model, neural_fit, neural_tune, neural_export
+from preface.lib.impute import ImputeOptions
+
+# Configure logging to suppress verbose output during tests
+logging.basicConfig(level=logging.ERROR)
+
+
+class TestNeural(unittest.TestCase):
+ def setUp(self):
+ self.temp_dir = tempfile.mkdtemp()
+ self.out_dir = Path(self.temp_dir)
+ self.n_samples = 20
+ self.n_features = 10
+ # Create synthetic data
+ self.X = np.random.rand(self.n_samples, self.n_features).astype(np.float32)
+ # Add some structure to Y to make learning possible (y = 2*x0 + 0.5)
+ self.y = (2 * self.X[:, 0] + 0.5).astype(np.float32)
+ # Groups for GroupShuffleSplit (ensure enough groups)
+ # With n_splits=5, test_size=0.2, we need enough groups.
+ # 20 samples, if we have 10 groups of 2 samples each.
+ self.groups = np.array([i // 2 for i in range(self.n_samples)])
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_create_model(self):
+ """Test model creation structure."""
+ input_dim = self.n_features
+ n_layers = 2
+ hidden_size = 32
+ learning_rate = 0.01
+ dropout_rate = 0.2
+
+ model = create_model(
+ input_dim=input_dim,
+ n_layers=n_layers,
+ hidden_size=hidden_size,
+ learning_rate=learning_rate,
+ dropout_rate=dropout_rate,
+ )
+
+ self.assertIsInstance(model, Model)
+ # Check input shape: (None, 10)
+ self.assertEqual(model.input_shape, (None, input_dim))
+ # Check output shape: (None, 1)
+ self.assertEqual(model.output_shape, (None, 1))
+
+ # Check number of layers
+ # Input layer is not always counted in len(model.layers) depending on how it's created,
+ # but with functional API:
+ # 1. Input (not in layers list usually if using Input() separately but here x = input_layer)
+ # Loop 2 times: Dense, Dropout -> 4 layers
+ # Output Dense -> 1 layer
+ # Total expected: 5 layers (plus maybe input layer if counted, let's check names)
+
+ # layers in create_model:
+ # loop range(n_layers): Dense, Dropout
+ # then Dense(1)
+ # So 2 * n_layers + 1
+ expected_layers = 2 * n_layers + 1
+ self.assertEqual(
+ len(model.layers), expected_layers + 1
+ ) # +1 for InputLayer which usually appears in functional model.layers
+
+ def test_neural_fit(self):
+ """Test model training."""
+ params = {
+ "n_layers": 1,
+ "hidden_size": 16,
+ "learning_rate": 0.01,
+ "dropout_rate": 0.1,
+ "epochs": 2, # Very fast
+ "batch_size": 4,
+ }
+
+ # Split data manually for test
+ x_train = self.X[:15]
+ y_train = self.y[:15]
+ x_test = self.X[15:]
+ y_test = self.y[15:]
+
+ model, preds = neural_fit(x_train, x_test, y_train, y_test, params)
+
+ self.assertIsInstance(model, Model)
+ self.assertEqual(preds.shape, (5, 1)) # 5 test samples
+
+ # Ensure predictions are floats
+ self.assertEqual(preds.dtype, np.float32)
+
+ def test_neural_tune(self):
+ """Test hyperparameter tuning with mocked n_trials."""
+ # Use a small n_components for PCA
+ n_components = 5
+
+ # We need enough data/groups for the internal split in neural_tune
+ # neural_tune uses GroupShuffleSplit(n_splits=5, test_size=0.2)
+ # It loops 5 times.
+ # This might be slow but with epochs set by optuna, we hope the suggested epochs are small?
+ # Optuna range for epochs is 20-100.
+ # We can't easily control the inner epochs unless we mock create_model or fit.
+ # BUT, we set n_trials=1, so it only runs once.
+ # 20 epochs on 20 samples is fast.
+
+ # We need to make sure we handle the return value
+ best_params = neural_tune(
+ x=self.X,
+ y=self.y,
+ groups=self.groups,
+ n_components=n_components,
+ outdir=self.out_dir,
+ impute_option=ImputeOptions.ZERO, # Use ZERO to avoid complex imputation in test
+ n_trials=1,
+ )
+
+ self.assertIsInstance(best_params, dict)
+ self.assertIn("n_layers", best_params)
+ self.assertIn("hidden_size", best_params)
+ self.assertIn("learning_rate", best_params)
+
+ # Check if plot was created
+ self.assertTrue((self.out_dir / "neural_tuning_history.png").exists())
+
+ def test_neural_export(self):
+ """Test ONNX export."""
+ model = create_model(
+ input_dim=self.n_features,
+ n_layers=1,
+ hidden_size=16,
+ learning_rate=0.01,
+ dropout_rate=0.1,
+ )
+ # We don't need to train it to export it
+ try:
+ onnx_model = neural_export(model)
+ self.assertIsInstance(onnx_model, onnx.ModelProto)
+ except ValueError as e:
+ # Handle potential Opset version issues gracefully if environment isn't perfect
+ if "Opset" in str(e):
+ logging.warning(
+ f"Skipping ONNX export validation due to Opset mismatch: {e}"
+ )
+ else:
+ raise e
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_svm.py b/tests/test_svm.py
new file mode 100644
index 0000000..c2874fb
--- /dev/null
+++ b/tests/test_svm.py
@@ -0,0 +1,89 @@
+import unittest
+import shutil
+import tempfile
+import numpy as np
+import logging
+from pathlib import Path
+from sklearn.svm import SVR
+import onnx
+from preface.lib.svm import svm_fit, svm_tune, svm_export
+from preface.lib.impute import ImputeOptions
+
+# Configure logging to suppress verbose output during tests
+logging.basicConfig(level=logging.ERROR)
+
+
+class TestSVM(unittest.TestCase):
+ def setUp(self):
+ self.temp_dir = tempfile.mkdtemp()
+ self.out_dir = Path(self.temp_dir)
+ self.n_samples = 20
+ self.n_features = 5
+ # Create synthetic data
+ self.X = np.random.rand(self.n_samples, self.n_features).astype(np.float32)
+ # Add some structure to Y to make learning possible (y = 2*x0 + 0.5)
+ self.y = (2 * self.X[:, 0] + 0.5).astype(np.float32)
+ # Groups for GroupShuffleSplit
+ self.groups = np.array([i // 2 for i in range(self.n_samples)])
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_svm_fit(self):
+ """Test SVM model training."""
+ params = {"C": 1.0}
+
+ # Split data manually for test
+ x_train = self.X[:15]
+ y_train = self.y[:15]
+ x_test = self.X[15:]
+ y_test = self.y[15:]
+
+ model, preds = svm_fit(x_train, x_test, y_train, y_test, params)
+
+ self.assertIsInstance(model, SVR)
+ self.assertEqual(preds.shape, (5,)) # 5 test samples, 1D array for SVM
+
+ # Ensure predictions are floats (can be float32 or float64 from sklearn)
+ self.assertTrue(np.issubdtype(preds.dtype, np.floating))
+
+ def test_svm_tune(self):
+ """Test hyperparameter tuning with mocked n_trials."""
+ n_components = 3
+
+ best_params = svm_tune(
+ x=self.X,
+ y=self.y,
+ groups=self.groups,
+ n_components=n_components,
+ outdir=self.out_dir,
+ impute_option=ImputeOptions.ZERO,
+ n_trials=1,
+ )
+
+ self.assertIsInstance(best_params, dict)
+ self.assertIn("C", best_params)
+
+ # Check if plot was created
+ self.assertTrue((self.out_dir / "svm_tuning_history.png").exists())
+
+ def test_svm_export(self):
+ """Test ONNX export."""
+ model = SVR(kernel="linear")
+ model.fit(self.X, self.y)
+
+ try:
+ onnx_model = svm_export(model)
+ self.assertIsInstance(onnx_model, onnx.ModelProto)
+ except ValueError as e:
+ # Handle potential Opset version issues gracefully
+ if "Opset" in str(e):
+ logging.warning(
+ f"Skipping ONNX export validation due to Opset mismatch: {e}"
+ )
+ else:
+ raise e
+
+
+if __name__ == "__main__":
+ unittest.main()
From 593c8aae14c5d805cd712c1cdd9a5ca4e068d085 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 19:55:50 +0100
Subject: [PATCH 47/50] add python tests to ci
---
.github/workflows/pr-checks.yml | 81 +++++----------------------------
pyproject.toml | 2 +
scripts/ci_checks.py | 75 ++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+), 70 deletions(-)
create mode 100644 scripts/ci_checks.py
diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml
index 9315cac..0c79ed3 100644
--- a/.github/workflows/pr-checks.yml
+++ b/.github/workflows/pr-checks.yml
@@ -6,7 +6,7 @@ on:
- master
jobs:
- pre-release-checks:
+ checks-and-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
@@ -14,75 +14,16 @@ jobs:
with:
fetch-depth: 0
- - name: Set up Python
- uses: actions/setup-python@v5
+ - name: Set up pixi
+ uses: prefix-dev/setup-pixi@v0.8.1
with:
- python-version: "3.11"
+ cache: true
- - name: Verify Version and Changelog
- shell: python
- run: |
- import sys
- import re
- import subprocess
- import os
-
- def get_version_from_content(content):
- match = re.search(r'__version__\s*=\s*["\']([^"\\]+)["\\]', content)
- if match:
- return match.group(1)
- return None
-
- print("--- Starting Checks ---")
-
- # 1. Get current version
- try:
- with open('src/preface/__init__.py', 'r') as f:
- current_content = f.read()
- current_version = get_version_from_content(current_content)
- if not current_version:
- print("Error: Could not find __version__ in src/preface/__init__.py")
- sys.exit(1)
- print(f"Current version: {current_version}")
- except FileNotFoundError:
- print("Error: src/preface/__init__.py not found")
- sys.exit(1)
-
- # 2. Check for 'dev' in version
- if 'dev' in current_version.lower():
- print("Error: Version contains 'dev'. PRs to master must be release versions.")
- sys.exit(1)
-
- # 3. Get master version
- try:
- # Fetch origin/master to ensure we have the reference
- subprocess.run(['git', 'fetch', 'origin', 'master'], check=True, capture_output=True)
- master_content = subprocess.check_output(['git', 'show', 'origin/master:src/preface/__init__.py']).decode('utf-8')
- master_version = get_version_from_content(master_content)
- print(f"Master version: {master_version}")
- except subprocess.CalledProcessError:
- print("Warning: Could not fetch version from origin/master (maybe it's the first commit?). Skipping bump check.")
- master_version = None
+ - name: Install dependencies
+ run: pixi install
+
+ - name: Run unit tests
+ run: pixi run pytest --cov=src/preface --cov-report=xml
- # 4. Check if version bumped
- if master_version and current_version == master_version:
- print(f"Error: Version {current_version} has not been bumped compared to master ({master_version}).")
- sys.exit(1)
-
- # 5. Check Changelog
- # Using git diff to check for modified files between origin/master and HEAD
- try:
- changed_files_output = subprocess.check_output(['git', 'diff', '--name-only', 'origin/master']).decode('utf-8')
- changed_files = changed_files_output.splitlines()
-
- if 'CHANGELOG.md' not in changed_files:
- print("Error: CHANGELOG.md has not been modified.")
- print("Changed files found:", changed_files)
- sys.exit(1)
- print("CHANGELOG.md modification found.")
-
- except subprocess.CalledProcessError as e:
- print(f"Error checking git diff: {e}")
- sys.exit(1)
-
- print("--- All checks passed successfully ---")
+ - name: Verify Version and Changelog
+ run: pixi run python scripts/ci_checks.py
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 19ea103..1c4402f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -57,3 +57,5 @@ PREFACE = { path = ".", editable = true }
[tool.pixi.dependencies]
pylint = ">=4.0.4,<5"
+pytest = ">=8,<9"
+pytest-cov = ">=5,<6"
diff --git a/scripts/ci_checks.py b/scripts/ci_checks.py
new file mode 100644
index 0000000..ac9c154
--- /dev/null
+++ b/scripts/ci_checks.py
@@ -0,0 +1,75 @@
+import sys
+import re
+import subprocess
+
+
+def get_version_from_content(content):
+ match = re.search(r'__version__\s*=\s*["\']([^"\\]+)["\\]', content)
+ if match:
+ return match.group(1)
+ return None
+
+
+print("--- Starting Checks ---")
+
+# 1. Get current version
+try:
+ with open("src/preface/__init__.py", "r") as f:
+ current_content = f.read()
+ current_version = get_version_from_content(current_content)
+ if not current_version:
+ print("Error: Could not find __version__ in src/preface/__init__.py")
+ sys.exit(1)
+ print(f"Current version: {current_version}")
+except FileNotFoundError:
+ print("Error: src/preface/__init__.py not found")
+ sys.exit(1)
+
+# 2. Check for 'dev' in version
+if "dev" in current_version.lower():
+ print("Error: Version contains 'dev'. PRs to master must be release versions.")
+ sys.exit(1)
+
+# 3. Get master version
+try:
+ # Fetch origin/master to ensure we have the reference
+ subprocess.run(
+ ["git", "fetch", "origin", "master"], check=True, capture_output=True
+ )
+ master_content = subprocess.check_output(
+ ["git", "show", "origin/master:src/preface/__init__.py"]
+ ).decode("utf-8")
+ master_version = get_version_from_content(master_content)
+ print(f"Master version: {master_version}")
+except subprocess.CalledProcessError:
+ print(
+ "Warning: Could not fetch version from origin/master (maybe it's the first commit?). Skipping bump check."
+ )
+ master_version = None
+
+# 4. Check if version bumped
+if master_version and current_version == master_version:
+ print(
+ f"Error: Version {current_version} has not been bumped compared to master ({master_version})."
+ )
+ sys.exit(1)
+
+# 5. Check Changelog
+# Using git diff to check for modified files between origin/master and HEAD
+try:
+ changed_files_output = subprocess.check_output(
+ ["git", "diff", "--name-only", "origin/master"]
+ ).decode("utf-8")
+ changed_files = changed_files_output.splitlines()
+
+ if "CHANGELOG.md" not in changed_files:
+ print("Error: CHANGELOG.md has not been modified.")
+ print("Changed files found:", changed_files)
+ sys.exit(1)
+ print("CHANGELOG.md modification found.")
+
+except subprocess.CalledProcessError as e:
+ print(f"Error checking git diff: {e}")
+ sys.exit(1)
+
+print("--- All checks passed successfully ---")
From c948734e87c77e0c8e4ee10dc580c74ae3aa9194 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 19:59:36 +0100
Subject: [PATCH 48/50] move ci script to .github dir
---
{scripts => .github/scripts}/ci_checks.py | 0
.github/workflows/pr-checks.yml | 2 +-
pixi.lock | 265 ++++++++++++++++------
3 files changed, 193 insertions(+), 74 deletions(-)
rename {scripts => .github/scripts}/ci_checks.py (100%)
diff --git a/scripts/ci_checks.py b/.github/scripts/ci_checks.py
similarity index 100%
rename from scripts/ci_checks.py
rename to .github/scripts/ci_checks.py
diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml
index 0c79ed3..aaa8795 100644
--- a/.github/workflows/pr-checks.yml
+++ b/.github/workflows/pr-checks.yml
@@ -26,4 +26,4 @@ jobs:
run: pixi run pytest --cov=src/preface --cov-report=xml
- name: Verify Version and Changelog
- run: pixi run python scripts/ci_checks.py
\ No newline at end of file
+ run: pixi run python .github/scripts/ci_checks.py
\ No newline at end of file
diff --git a/pixi.lock b/pixi.lock
index 3867d9d..59675ba 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -15,8 +15,11 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.13.1-py313h3dea7bd_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda
@@ -31,14 +34,21 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.11-hc97d973_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
@@ -62,7 +72,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
@@ -90,16 +99,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
@@ -124,7 +129,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
@@ -138,8 +142,11 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_8.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.13.1-py313hfa222a2_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45-default_h1979696_104.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.3-hfae3067_0.conda
@@ -154,14 +161,21 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.0-h8e36d6e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.13.11-h4c0d347_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h561c983_103.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda
@@ -185,7 +199,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
@@ -212,16 +225,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
@@ -246,7 +255,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
@@ -259,8 +267,11 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/coverage-7.13.1-py313h65a2061_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
@@ -271,14 +282,21 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
@@ -300,7 +318,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
@@ -327,16 +344,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
@@ -361,7 +374,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
@@ -646,6 +658,50 @@ packages:
- pytest-xdist ; extra == 'test-no-images'
- wurlitzer ; extra == 'test-no-images'
requires_python: '>=3.11'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.13.1-py313h3dea7bd_0.conda
+ sha256: 4275280f4fcef6cd0a0e5cd236120d7454a11390dd4c271378bf90bc563f6780
+ md5: 82315acb438e857f809f556e2dcdb822
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - python >=3.13,<3.14.0a0
+ - python_abi 3.13.* *_cp313
+ - tomli
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/coverage?source=hash-mapping
+ size: 393234
+ timestamp: 1766951417242
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.13.1-py313hfa222a2_0.conda
+ sha256: 08b106da86fb07a8b97a0d7c111ce094cd240831701322fe459c1cc6b6940734
+ md5: 2673bb6f13a235122237b3c321b5dcbb
+ depends:
+ - libgcc >=14
+ - python >=3.13,<3.14.0a0
+ - python_abi 3.13.* *_cp313
+ - tomli
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/coverage?source=hash-mapping
+ size: 393945
+ timestamp: 1766952440036
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/coverage-7.13.1-py313h65a2061_0.conda
+ sha256: 46e4af43bd60580fda7955cc6c21b3a40465ef25a98c2a256419dc74caae56b0
+ md5: 3283d95f985c7f293cb13bb7e33500a5
+ depends:
+ - __osx >=11.0
+ - python >=3.13,<3.14.0a0
+ - python >=3.13,<3.14.0a0 *_cp313
+ - python_abi 3.13.* *_cp313
+ - tomli
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/coverage?source=hash-mapping
+ size: 393649
+ timestamp: 1766951606379
- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
name: cycler
version: 0.12.1
@@ -671,6 +727,17 @@ packages:
- pkg:pypi/dill?source=hash-mapping
size: 94889
timestamp: 1764517905571
+- 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
+ size: 21333
+ timestamp: 1763918099466
- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
name: flatbuffers
version: 25.12.19
@@ -887,11 +954,17 @@ packages:
- pkg:pypi/importlib-metadata?source=hash-mapping
size: 34641
timestamp: 1747934053147
-- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl
- name: iniconfig
- version: 2.3.0
- sha256: f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12
- requires_python: '>=3.10'
+- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
+ sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19
+ md5: 9614359868482abba1bd15ce465e3c42
+ depends:
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/iniconfig?source=compressed-mapping
+ size: 13387
+ timestamp: 1760831448842
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
sha256: 13b0005877f553eb2e5c50447c9d0047e7257124ec2d1569d7dad35697790237
md5: 55a61979242077b2cc377c74326ea9f0
@@ -1939,11 +2012,18 @@ packages:
version: 3.11.5
sha256: 75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- name: packaging
- version: '25.0'
- sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484
- requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
+ sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991
+ md5: 58335b26c38bf4a20f399384c33cbcf9
+ depends:
+ - python >=3.8
+ - python
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/packaging?source=hash-mapping
+ size: 62477
+ timestamp: 1745345660407
- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
name: pandas
version: 2.3.3
@@ -2375,21 +2455,22 @@ packages:
- xarray ; extra == 'dev-optional'
- plotly[dev-optional] ; extra == 'dev'
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl
- name: pluggy
- version: 1.6.0
- sha256: e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
- requires_dist:
- - pre-commit ; extra == 'dev'
- - tox ; extra == 'dev'
- - pytest ; extra == 'testing'
- - pytest-benchmark ; extra == 'testing'
- - coverage ; extra == 'testing'
- requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ sha256: e14aafa63efa0528ca99ba568eaf506eb55a0371d12e6250aaaa61718d2eb62e
+ md5: d7585b6550ad04c8c5e21097ada2888e
+ depends:
+ - python >=3.9
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pluggy?source=compressed-mapping
+ size: 25877
+ timestamp: 1764896838868
- pypi: ./
name: preface
version: 1.0.0.dev0
- sha256: f7f2f9b867798a3ea01c31d73dee363c8dea713fde35f9a0d7c4eec6786c9aa0
+ sha256: 6682492844d8a0a8cf33b43218e4bb1b4501ac723375e8697f7bf1a202889956
requires_dist:
- pandas>=2.3.3,<3
- numpy>=2.4.0,<3
@@ -2409,7 +2490,7 @@ packages:
- skl2onnx>=1.19.1,<2
- onnxconverter-common>=1.16.0,<2
- onnxruntime>=1.23.2,<2
- - tf2onnx
+ - tf2onnx>=1.8.4,<2
requires_python: '>=3.11,<3.14'
- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
name: protobuf
@@ -2426,13 +2507,17 @@ packages:
version: 6.33.2
sha256: d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl
- name: pygments
- version: 2.19.2
- sha256: 86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
- requires_dist:
- - colorama>=0.4.6 ; extra == 'windows-terminal'
- requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
+ sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a
+ md5: 6b6ece66ebcae2d5f326c77ef2c5a066
+ depends:
+ - python >=3.9
+ license: BSD-2-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/pygments?source=hash-mapping
+ size: 889287
+ timestamp: 1750615908735
- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
sha256: ad0bb78785ab385d0afcca4a55e0226d8e6710ebad6450caa552f5fe61c2f6a0
md5: 3a830511a81b99b67a1206a9d29b44b3
@@ -2461,26 +2546,41 @@ packages:
- railroad-diagrams ; extra == 'diagrams'
- jinja2 ; extra == 'diagrams'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl
- name: pytest
- version: 9.0.2
- sha256: 711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b
- requires_dist:
- - colorama>=0.4 ; sys_platform == 'win32'
- - exceptiongroup>=1 ; python_full_version < '3.11'
- - iniconfig>=1.0.1
- - packaging>=22
- - pluggy>=1.5,<2
- - pygments>=2.7.2
- - tomli>=1 ; python_full_version < '3.11'
- - argcomplete ; extra == 'dev'
- - attrs>=19.2 ; extra == 'dev'
- - hypothesis>=3.56 ; extra == 'dev'
- - mock ; extra == 'dev'
- - requests ; extra == 'dev'
- - setuptools ; extra == 'dev'
- - xmlschema ; extra == 'dev'
- requires_python: '>=3.10'
+- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhcf101f3_1.conda
+ sha256: 39f41a52eb6f927caf5cd42a2ff98a09bb850ce9758b432869374b6253826962
+ md5: da0c42269086f5170e2b296878ec13a6
+ depends:
+ - pygments >=2.7.2
+ - python >=3.10
+ - iniconfig >=1
+ - packaging >=20
+ - pluggy >=1.5,<2
+ - tomli >=1
+ - colorama >=0.4
+ - exceptiongroup >=1
+ - python
+ constrains:
+ - pytest-faulthandler >=2
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pytest?source=hash-mapping
+ size: 294852
+ timestamp: 1762354779909
+- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
+ sha256: 218306243faf3c36347131c2b36bb189daa948ac2e92c7ab52bb26cc8c157b3c
+ md5: c54c0107057d67ddf077751339ec2c63
+ depends:
+ - coverage >=5.2.1
+ - pytest >=4.6
+ - python >=3.8
+ - toml
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pytest-cov?source=hash-mapping
+ size: 25507
+ timestamp: 1711411153367
- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
name: pytest-timeout
version: 2.4.0
@@ -3485,6 +3585,18 @@ packages:
purls: []
size: 3125484
timestamp: 1763055028377
+- conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
+ sha256: fd30e43699cb22ab32ff3134d3acf12d6010b5bbaa63293c37076b50009b91f8
+ md5: d0fc809fa4c4d85e959ce4ab6e1de800
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/toml?source=hash-mapping
+ size: 24017
+ timestamp: 1764486833072
- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
sha256: cb77c660b646c00a48ef942a9e1721ee46e90230c7c570cdeb5a893b5cce9bff
md5: d2732eb636c264dc9aa4cbee404b1a53
@@ -3534,11 +3646,18 @@ packages:
- shellingham>=1.3.0
- rich>=10.11.0
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl
- name: typing-extensions
- version: 4.15.0
- sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
- requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
+ sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731
+ md5: 0caa1af407ecff61170c9437a808404d
+ depends:
+ - python >=3.10
+ - python
+ license: PSF-2.0
+ license_family: PSF
+ purls:
+ - pkg:pypi/typing-extensions?source=hash-mapping
+ size: 51692
+ timestamp: 1756220668932
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
name: tzdata
version: '2025.3'
From 4880acb4116c396f0a1f23bb995839ea57e40fbc Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 20:20:53 +0100
Subject: [PATCH 49/50] try to fix opset selection
---
src/preface/lib/export_onnx.py | 36 +++++++++++++---------------------
src/preface/lib/functions.py | 2 +-
src/preface/lib/impute.py | 2 +-
src/preface/lib/neural.py | 1 +
src/preface/lib/svm.py | 2 +-
src/preface/lib/xgboost.py | 2 +-
tests/test_plot.py | 10 ----------
7 files changed, 19 insertions(+), 36 deletions(-)
diff --git a/src/preface/lib/export_onnx.py b/src/preface/lib/export_onnx.py
index 060906d..d1b8687 100644
--- a/src/preface/lib/export_onnx.py
+++ b/src/preface/lib/export_onnx.py
@@ -12,8 +12,12 @@
from tensorflow.keras import Model # type: ignore
from xgboost import XGBRegressor
+from preface.lib.neural import neural_export
+from preface.lib.svm import svm_export
+from preface.lib.xgboost import xgboost_export
-def _ensure_opset(model_proto: onnx.ModelProto, version: int = 18) -> onnx.ModelProto:
+
+def _ensure_opset(model_proto: onnx.ModelProto, version: int = 13) -> onnx.ModelProto:
"""
Force the default domain opset to a specific version.
"""
@@ -31,14 +35,14 @@ def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
pca_onnx = convert_sklearn(
pca,
initial_types=pca_initial_type,
- target_opset=18,
+ target_opset=13,
)
- _ensure_opset(pca_onnx, 18) # type: ignore
+ _ensure_opset(pca_onnx, 13) # type: ignore
return pca_onnx # type: ignore
-def export_ensemble(
+def ensemble_export(
models: List[
Tuple[
SimpleImputer | KNNImputer | IterativeImputer,
@@ -66,18 +70,17 @@ def export_ensemble(
# 1. Convert Imputer
initial_type = [("input", FloatTensorType([None, input_dim]))]
imputer_onnx = convert_sklearn(
- imputer, initial_types=initial_type, target_opset={"": 12, "ai.onnx.ml": 2}
+ imputer, initial_types=initial_type, target_opset={"": 13, "ai.onnx.ml": 2}
)
- _ensure_opset(imputer_onnx, 12) # type: ignore
+ _ensure_opset(imputer_onnx, 13) # type: ignore
# Prefix Imputer
imputer_onnx = add_prefix(imputer_onnx, prefix="imputer_") # type: ignore
imputer_out_name = imputer_onnx.graph.output[0].name # type: ignore
# 2. Convert PCA
- pca_onnx = pca_to_onnx(pca, input_dim)
+ pca_onnx = pca_export(pca, input_dim)
pca_in_name = pca_onnx.graph.input[0].name # type: ignore
- pca_out_name = pca_onnx.graph.output[0].name # type: ignore
# Merge Imputer + PCA
current_model = merge_models(
@@ -85,30 +88,19 @@ def export_ensemble(
pca_onnx, # type: ignore
io_map=[(imputer_out_name, pca_in_name)], # type: ignore
)
- current_out_name = pca_out_name
- n_comps = pca.n_components_
# 3. Convert Model
model_type = "unknown"
if isinstance(model, Model):
model_type = "nn"
- current_model, info = export_nn(
- model, n_comps, current_model, current_out_name, i
- )
- split_info.extend(info)
+ current_model = neural_export(model)
elif isinstance(model, SVR):
- current_model, info = export_svm(
- model, n_comps, current_model, current_out_name
- )
- split_info.extend(info)
+ current_model = svm_export(model)
elif isinstance(model, XGBRegressor):
model_type = "xgb"
- current_model, info = export_xgb(
- model, n_comps, current_model, current_out_name
- )
- split_info.extend(info)
+ current_model = xgboost_export(model)
# Prefix everything in this split's graph
prefixed_model = add_prefix(current_model, prefix=split_prefix)
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index c42631d..21bced5 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -60,5 +60,5 @@ def fit_rlm(x_values: npt.NDArray, y_values: npt.NDArray) -> tuple[float, float]
def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
"""Export PCA model to ONNX format."""
initial_type = [("input", FloatTensorType([None, input_dim]))]
- pca_onnx = convert_sklearn(pca, initial_types=initial_type, target_opset=18)
+ pca_onnx = convert_sklearn(pca, initial_types=initial_type, target_opset=13)
return pca_onnx # type: ignore
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index e567588..e5b4eaf 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -87,5 +87,5 @@ def impute_export(
initial_type = [("impute_input", FloatTensorType([None, input_dim]))]
- imputer_onnx = convert_sklearn(imputer, initial_types=initial_type, target_opset=18)
+ imputer_onnx = convert_sklearn(imputer, initial_types=initial_type, target_opset=13)
return imputer_onnx # type: ignore
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index e38d635..7747c87 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -105,6 +105,7 @@ def objective(trial) -> float:
)
study.optimize(objective, n_trials=n_trials)
+ outdir.mkdir(parents=True, exist_ok=True)
fig = optuna.visualization.plot_optimization_history(study)
fig.write_image(outdir / "neural_tuning_history.png")
return study.best_params
diff --git a/src/preface/lib/svm.py b/src/preface/lib/svm.py
index 8d64521..00a865a 100644
--- a/src/preface/lib/svm.py
+++ b/src/preface/lib/svm.py
@@ -89,6 +89,6 @@ def svm_export(model: SVR) -> onnx.ModelProto:
"""Export SVM model to ONNX format."""
initial_type = [("svm_input", FloatTensorType([None, model.n_features_in_]))]
onnx_model = onnxmltools.convert_sklearn(
- model, initial_types=initial_type, target_opset=15
+ model, initial_types=initial_type, target_opset=13
)
return onnx_model # type: ignore
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 100fe92..3217f49 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -106,6 +106,6 @@ def xgboost_export(model: XGBRegressor) -> onnx.ModelProto:
initial_type = [("xgboost_input", FloatTensorType([None, model.n_features_in_]))]
onnx_model = onnxmltools.convert_xgboost(
- model, initial_types=initial_type, target_opset=18
+ model, initial_types=initial_type, target_opset=13
)
return onnx_model
diff --git a/tests/test_plot.py b/tests/test_plot.py
index 214769f..0f0e036 100644
--- a/tests/test_plot.py
+++ b/tests/test_plot.py
@@ -1,6 +1,5 @@
"""Unit tests for plotting functions."""
-import os
import shutil
import unittest
from pathlib import Path
@@ -10,7 +9,6 @@
# Import the functions to be tested, including the private one for direct testing
from preface.lib.plot import (
_calculate_regression_metrics,
- fit_rlm,
plot_ffx,
plot_pca,
plot_regression_performance,
@@ -43,14 +41,6 @@ def test_calculate_regression_metrics(self):
self.assertAlmostEqual(metrics["mae"], 0.14, places=2)
self.assertAlmostEqual(metrics["slope"], 1.0, places=2)
- def test_fit_rlm(self):
- """Test the fit_rlm function with a clear linear relationship."""
- x = np.array([1, 2, 3, 4, 5])
- y = 2 * x + 1 # slope=2, intercept=1
- intercept, slope = fit_rlm(x, y)
- self.assertAlmostEqual(intercept, 1.0, places=5)
- self.assertAlmostEqual(slope, 2.0, places=5)
-
def test_plot_regression_performance_smoke(self):
"""Smoke test for plot_regression_performance."""
y_true = np.random.rand(50) * 20
From de7a3f45039fa9699f85f61388edf6266e828365 Mon Sep 17 00:00:00 2001
From: Matthias De Smet <11850640+matthdsm@users.noreply.github.com>
Date: Fri, 2 Jan 2026 22:21:33 +0100
Subject: [PATCH 50/50] fix dependency versions, fix opset
---
Dockerfile | 2 +-
pixi.lock | 11238 ++++++++++++++++++++++---------
pyproject.toml | 57 +-
src/preface/lib/export_onnx.py | 10 +-
src/preface/lib/functions.py | 2 +-
src/preface/lib/impute.py | 2 +-
src/preface/lib/neural.py | 2 +-
src/preface/lib/svm.py | 2 +-
src/preface/lib/xgboost.py | 21 +-
9 files changed, 7962 insertions(+), 3374 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index dee425c..0ec8802 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,7 +10,7 @@ RUN pixi install --frozen --locked
RUN pixi run pip install --no-deps .
# Stage 2: Runtime
-FROM python:3.13-slim
+FROM python:3.12-slim
WORKDIR /app
diff --git a/pixi.lock b/pixi.lock
index 59675ba..66fa368 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -11,375 +11,726 @@ environments:
linux-64:
- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
- - conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py313h78bf25f_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/_x86_64-microarch-level-1-3_x86_64.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.17.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.1-hb03c661_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py312h7900ff3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/astunparse-1.6.3-pyhd8ed1ab_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py312h90b7ffd_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-h3394656_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.13.1-py313h3dea7bd_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/colorlog-6.10.1-pyh707e725_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py312hd9148b4_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.13.1-py312h8a5da7c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hd9c7081_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.16.2-h24cb091_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.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/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-25.2.10-hb7832b1_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/linux-64/fontconfig-2.15.0-h7e30c49_1.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/linux-64/fonttools-4.61.1-py312h8a5da7c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/gast-0.7.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/gmpy2-2.2.1-py312hcaba1f9_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/google-pasta-0.2.0-pyhd8ed1ab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.3.0-py312h1289d80_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/grpcio-1.73.1-py312h6f3464c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/h5py-3.15.1-nompi_py312ha4f8f14_101.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-12.2.0-h15599e2_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h1b119a7_104.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/keras-3.12.0-pyh753f3f9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.9-py312h0a2e395_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.17-h717163a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.4-h3f801dc_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.7-default_h99862b1_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-21.1.7-default_h746c552_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-hb8b1518_5.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.17.0-h4e3cde8_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.125-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.3-h6548e54_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-h5347b49_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/libml_dtypes-headers-0.5.4-h707e725_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.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/libopenblas-0.3.30-pthreads_h94d23a6_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.53-h421ea60_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.1-h5c52fec_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libtensorflow_cc-2.19.1-cpu_hf7abd0a_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libtensorflow_framework-2.19.1-cpu_h12ecb4a_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.328.1-h5279c79_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libxgboost-3.1.2-cpu_h2ebb00f_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.13.1-hca5e8e5_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-ha9997c6_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.1-h26afc86_0.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.1-hb9d3cd8_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.10-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.10.8-py312h7900ff3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.10.8-py312he3d6523_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ml_dtypes-0.5.4-np2py312h0f77346_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/mpc-1.3.1-h24ddda3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/mpfr-4.2.1-h90cbb55_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/namex-0.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.14.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.0-py312h33ff503_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/onnx-1.20.0-py312h75e9504_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/onnxconverter-common-1.16.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/onnxmltools-1.14.0-pyhe01879c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/onnxruntime-1.22.2-py312hb39aaa6_1_cpu.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.10-he970967_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/optree-0.18.0-py312hd9148b4_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.6.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-2.3.3-py312hf79963d_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.0-py312h50c33e8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.5.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.31.1-py312hb8af0ac_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/py-xgboost-3.1.2-cpu_pyh718b53a_2.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/pyside6-6.10.1-py312h9da60e5_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/pytest-8.4.2-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.11-hc97d973_100_cp313.conda
- - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.12-hd63d673_1_cpython.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_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.10.1-h6f76662_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.3-py312h54fa4ab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/skl2onnx-1.19.1-pyhe01879c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.45-py312h4c3975b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sympy-1.14.0-pyh2585a3b_105.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tensorboard-2.19.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/tensorboard-data-server-0.7.0-py312h4eba8b5_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/tensorflow-2.19.1-cpu_py312h69ecde4_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/tensorflow-base-2.19.1-cpu_py312h0afb428_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/tensorflow-estimator-2.19.1-cpu_py312h6e6b5e2_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/termcolor-3.3.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tf2onnx-1.16.1-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.3-py312h4c3975b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.21.0-pyhbb89825_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.21.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.21.0-hd63da06_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
- - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.0-py312h4c3975b_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.24.0-hd6090a7_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.0.1-py312h4c3975b_1.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/noarch/xgboost-3.1.2-cpu_pyhb39878e_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.46-hb03c661_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.12-h4f16b4b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.6-hb9d3cd8_2.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_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.6-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.4-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.6-hb9d3cd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
- - pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/84/a7/38aa564871d062c11538d65c575af9c7e057be880c09ecbd899dd1abfa83/onnx-1.20.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/f2/2b/b57c8a2466a3126dbe0a792f56ad7290949b02f47b86216cd47d857e4b77/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/46/bf/0993b5a056759ba65145effe3a79dd5a939d4a070eaa5da2ee3180fbb13f/orjson-3.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/43/f1/b392952200f3393bb06fbc4dd975fc63a6843261705839355560b7264eb2/simplejson-3.20.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- - pypi: https://files.pythonhosted.org/packages/5e/ab/c60fcc137fa685533bb31e721de3ecc88959d393830d59d0204c5cbd2c85/xgboost-3.1.2-py3-none-manylinux_2_28_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/20/05/ed9b2571bbf38f1a2425391f18e3ac11cb1e91482c22d644a1640dea9da7/simplejson-3.20.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ - pypi: https://files.pythonhosted.org/packages/81/68/dddd76117df2ef14c943c6bbb6618be5c9401280046f4ddfc9fb4596a1b8/statsmodels-0.14.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: ./
linux-aarch64:
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2
- - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/astroid-4.0.2-py313hd81a959_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.17.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.1-he30d5cf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/astroid-4.0.2-py312h996f985_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/astunparse-1.6.3-pyhd8ed1ab_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py312h3d8e7d4_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-1.2.0-hd651790_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-bin-1.2.0-he30d5cf_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py312hac7b6a9_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h83712da_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.13.1-py313hfa222a2_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/colorlog-6.10.1-pyh707e725_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/contourpy-1.3.3-py312h4f740d2_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.13.1-py312hd077ced_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cyrus-sasl-2.1.28-h6c5dea3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/dbus-1.16.2-h70963c4_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/double-conversion-3.4.0-hfae3067_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.12.23-hb76e14f_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/linux-aarch64/fontconfig-2.15.0-h8dda3cd_1.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/linux-aarch64/fonttools-4.61.1-py312ha4530ae_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.1-h8af1aa0_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/gast-0.7.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmp-6.3.0-h0a1ffab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmpy2-2.2.1-py312h35d709e_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/google-pasta-0.2.0-pyhd8ed1ab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/greenlet-3.3.0-py312h1ab2c47_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/grpcio-1.67.1-py312h37c5e5d_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/h5py-3.15.1-nompi_py312hb54937b_101.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-12.2.0-he4899c9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf5-1.14.6-nompi_hc619b4a_104.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-75.1-hf9b3779_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45-default_h1979696_104.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/keras-3.12.0-pyh753f3f9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kiwisolver-1.4.9-py312h1683e8e_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.3-h50a48e9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.17-hc88f144_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45-default_h1979696_105.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.0.0-hfdc4d58_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20240722.0-cxx17_h18dbdb1_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libaec-1.1.4-h1e66f74_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.2.0-he30d5cf_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.2.0-he30d5cf_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.2.0-he30d5cf_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp21.1-21.1.7-default_he95a3c9_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-21.1.7-default_h94a09a5_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h5cdc715_5.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.17.0-h7bfdcfb_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdrm-2.4.125-he30d5cf_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libegl-1.7.0-hd24410f_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.3-hfae3067_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-hd65408f_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.1-h8af1aa0_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.1-hdae7a39_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-1.7.0-hd24410f_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.3-hf53f6bf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglvnd-1.7.0-hd24410f_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglx-1.7.0-hd24410f_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgrpc-1.67.1-hf7ccdd3_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm21-21.1.8-hfd2ba90_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.1-h86ecc28_2.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-h86ecc28_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.51.1-h022381a_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.2-h1022ec0_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/libml_dtypes-headers-0.5.4-h707e725_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.67.0-ha888d0e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libntlm-1.4-hf897c2e_1002.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopengl-1.7.0-hd24410f_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpciaccess-0.18-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.53-h1abf092_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.1-haf03d9f_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-5.28.3-h44a3b7b_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2024.07.02-h18dbdb1_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.51.1-h022381a_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtensorflow_cc-2.18.0-cpu_h26186cf_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtensorflow_framework-2.18.0-cpu_h78d15be_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvulkan-loader-1.4.328.1-h8b8848b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxgboost-3.1.2-cpu_hb699d04_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxkbcommon-1.13.1-h3c6a4c8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.1-h8591a01_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.1-h788dabe_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxslt-1.1.43-h6700d25_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.10-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py312hd077ced_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.10.8-py312h8025657_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.10.8-py312h9d0c5ba_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ml_dtypes-0.4.0-py312ha2895bd_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mpc-1.3.1-h783934e_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mpfr-4.2.1-h2305555_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/namex-0.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.14.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.0-py312h6615c27_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/onnx-1.17.0-py312hf4577d9_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/onnxconverter-common-1.16.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/onnxmltools-1.14.0-pyhe01879c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/onnxruntime-1.22.2-py312hc28d7f2_1_cpu.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openldap-2.6.10-h30c48ee_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.0-h8e36d6e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/optree-0.18.0-py312h4f740d2_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.6.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pandas-2.3.3-py312hdc0efb6_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.0-py312h3b21937_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.5.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/protobuf-5.28.3-py312h6f74592_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/py-xgboost-3.1.2-cpu_pyh718b53a_2.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyside6-6.10.1-py312h4810df5_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/pytest-8.4.2-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
- - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.13.11-h4c0d347_100_cp313.conda
- - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.12-h91f4b29_1_cpython.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py312ha4530ae_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qhull-2020.2-h70be974_5.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qt6-main-6.10.1-h9c50542_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2024.07.02-haa97905_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/scikit-learn-1.8.0-np2py312hca49013_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/scipy-1.16.3-py312he5b0e10_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/skl2onnx-1.19.1-pyhe01879c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.2-he774c54_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlalchemy-2.0.45-py312hefbd42c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sympy-1.14.0-pyh2585a3b_105.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tensorboard-2.18.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorboard-data-server-0.7.0-py312hf3624cf_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorflow-2.18.0-cpu_py312h0267799_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorflow-base-2.18.0-cpu_py312h7226aab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorflow-estimator-2.18.0-cpu_py312h15e21a2_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/termcolor-3.3.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tf2onnx-1.16.1-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h561c983_103.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.3-py312hefbd42c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.21.0-pyhbb89825_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.21.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.21.0-hd63da06_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
- - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/unicodedata2-17.0.0-py312hcd1a082_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wayland-1.24.0-h4f8a99f_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.0.1-py312hcd1a082_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-0.4.1-hca56bd8_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-cursor-0.1.6-he30d5cf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-image-0.4.0-h5c728e9_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-keysyms-0.4.1-h5c728e9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-renderutil-0.3.10-h5c728e9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-wm-0.4.2-h5c728e9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/xgboost-3.1.2-cpu_pyhb39878e_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.46-he30d5cf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.12-hca56bd8_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxcomposite-0.4.6-h86ecc28_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxcursor-1.2.3-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdamage-1.1.6-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.6-h57736b2_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.4-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxxf86vm-1.1.6-h86ecc28_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.2-ha7cb516_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda
- - pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/78/bb/b98732309f2f6beb4cdcf7b955d7bbfd75a191185370ee21233373db381e/onnx-1.20.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1c/a1/428ee29c6eaf09a6f6be56f836213f104618fb35ac6cc586ff0f477263eb/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/52/8d/544e77d7a29d90cf4d9eecd0ae801c688e7f3d1adfa2ebae5e1e94d38ab9/orjson-3.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/09/1d/171009bd35c7099d72ef6afd4bb13527bab469965c968a17d69a203d62a6/simplejson-3.20.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- - pypi: https://files.pythonhosted.org/packages/70/2f/5418f4b1deaf0886caf81c5e056299228ac2fc09b965a2dfe5e4496331c8/xgboost-3.1.2-py3-none-manylinux_2_28_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/97/ec/5c6db08e42f380f005d03944be1af1a6bd501cc641175429a1cbe7fb23b9/simplejson-3.20.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ - pypi: https://files.pythonhosted.org/packages/48/f5/3a73b51e6450c31652c53a8e12e24eac64e3824be816c0c2316e7dbdcb7d/statsmodels-0.14.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- pypi: ./
osx-arm64:
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/astroid-4.0.2-py313h8f79df9_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/noarch/absl-py-2.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.17.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/astroid-4.0.2-py312h81bd7bf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/astunparse-1.6.3-pyhd8ed1ab_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.3.0-py312h44dc372_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2
+ - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/coverage-7.13.1-py313h65a2061_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/colorlog-6.10.1-pyh707e725_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/contourpy-1.3.3-py312h84eede6_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/coverage-7.13.1-py312h04c11ed_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.12.23-h28594ff_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fonttools-4.61.1-py312h5748b74_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.14.1-hce30654_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/gast-0.7.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/giflib-5.2.2-h93a5062_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gmp-6.3.0-h7bae524_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gmpy2-2.2.1-py312hee6aa52_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/google-pasta-0.2.0-pyhd8ed1ab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/greenlet-3.3.0-py312h455b684_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/grpcio-1.67.1-py312he4e58e5_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/h5py-3.15.1-nompi_py312h4eecd6b_101.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-1.14.6-nompi_hd3baa01_104.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/keras-3.12.0-pyh753f3f9_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.4.9-py312hd8c8125_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.17-h7eeda09_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240722.0-cxx17_h07bc746_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.4-h51d1e36_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.17.0-hdece5d2_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.67.1-h0a426d6_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/libml_dtypes-headers-0.5.4-h707e725_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.53-hfab5511_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-5.28.3-h3bd63a1_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2024.07.02-h07bc746_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h1b79a29_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtensorflow_cc-2.18.0-cpu_hf321e49_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtensorflow_framework-2.18.0-cpu_h2398287_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxgboost-3.1.2-cpu_h64a644d_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.10-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h5748b74_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-3.10.8-py312h1f38498_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-base-3.10.8-py312h605b88b_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ml_dtypes-0.4.0-py312hcd31e36_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mpc-1.3.1-h8f1351a_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mpfr-4.2.1-hb693164_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/namex-0.1.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.14.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.0-py312he281c53_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/onnx-1.17.0-py312hc636692_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/onnxconverter-common-1.16.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/onnxmltools-1.14.0-pyhe01879c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/onnxruntime-1.22.2-py312h4d4766a_1_cpu.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/optree-0.18.0-py312h84eede6_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.6.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-2.3.3-py312h5978115_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pillow-12.1.0-py312h4e908a4_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.5.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-5.28.3-py312hd8f9ff3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/py-xgboost-3.1.2-cpu_pyh718b53a_2.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.1-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/pytest-8.4.2-pyhcf101f3_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
- - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_100_cp313.conda
- - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.12-h18782d2_1_cpython.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h5748b74_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/re2-2024.07.02-h6589ca4_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.16.3-py312h39258fd_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/skl2onnx-1.19.1-pyhe01879c_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.45-py312h4409184_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sympy-1.14.0-pyh2585a3b_105.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tensorboard-2.18.0-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorboard-data-server-0.7.0-py312h9536bd2_4.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorflow-2.18.0-cpu_py312hb6b62e0_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorflow-base-2.18.0-cpu_py312h81ab8d0_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorflow-estimator-2.18.0-cpu_py312h5e86b3d_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/termcolor-3.3.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tf2onnx-1.16.1-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.4-py312h4409184_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.21.0-pyhbb89825_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.21.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.21.0-hd63da06_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
- - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.0-py312h4409184_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.2-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.4-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-2.0.1-py312h4409184_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/xgboost-3.1.2-cpu_pyhb39878e_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
- - pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.2-hed4e4f5_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda
- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/5e/19/2caa972a31014a8cb4525f715f2a75d93caef9d4b9da2809cc05d0489e43/onnx-1.20.0-cp312-abi3-macosx_12_0_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/3d/41/fba0cabccecefe4a1b5fc8020c44febb334637f133acefc7ec492029dd2c/onnxruntime-1.23.2-cp313-cp313-macosx_13_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/ef/a4/8052a029029b096a78955eadd68ab594ce2197e24ec50e6b6d2ab3f4e33b/orjson-3.11.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl
- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
- - pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7a/4d/30dfef83b9ac48afae1cf1ab19c2867e27b8d22b5d9f8ca7ce5a0a157d8c/simplejson-3.20.2-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
- - pypi: https://files.pythonhosted.org/packages/f4/c6/ed928cb106f56ab73b3f4edb5287c1352251eb9225b5932d3dd5e2803f60/xgboost-3.1.2-py3-none-macosx_12_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/ad/f1/efd09efcc1e26629e120fef59be059ce7841cc6e1f949a4db94f1ae8a918/simplejson-3.20.2-cp312-cp312-macosx_11_0_arm64.whl
+ - pypi: https://files.pythonhosted.org/packages/05/30/affbabf3c27fb501ec7b5808230c619d4d1a4525c07301074eb4bda92fa9/statsmodels-0.14.6-cp312-cp312-macosx_11_0_arm64.whl
- pypi: ./
packages:
- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
@@ -416,67 +767,294 @@ packages:
purls: []
size: 23712
timestamp: 1650670790230
-- pypi: https://files.pythonhosted.org/packages/8f/aa/ba0014cc4659328dc818a28827be78e6d97312ab0cb98105a770924dc11e/absl_py-2.3.1-py3-none-any.whl
- name: absl-py
- version: 2.3.1
- sha256: eeecf07f0c2a93ace0772c92e596ace6d3d3996c042b2128459aaae2a76de11d
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl
- name: alembic
- version: 1.17.2
- sha256: f483dd1fe93f6c5d49217055e4d15b905b425b6af906746abb35b69c1996c4e6
- requires_dist:
- - sqlalchemy>=1.4.0
+- 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: []
+ size: 8325
+ timestamp: 1764092507920
+- conda: https://conda.anaconda.org/conda-forge/noarch/_x86_64-microarch-level-1-3_x86_64.conda
+ build_number: 3
+ sha256: 5f9029eaa78eb13a5499b7a2b012a47a18136b2d41bad99bb7b1796d1fc2b179
+ md5: 225cb2e9b9512730a92f83696b8fbab8
+ depends:
+ - __archspec 1.* x86_64
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 9818
+ timestamp: 1764034326319
+- conda: https://conda.anaconda.org/conda-forge/noarch/absl-py-2.3.1-pyhd8ed1ab_0.conda
+ sha256: ec7a804be25350c310be7e0fffdbf4006fd22a650bf316513bdd71cb922944bf
+ md5: 7d4f1ddc43d323c916b2c744835eb093
+ depends:
+ - python >=3.9
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/absl-py?source=hash-mapping
+ size: 109408
+ timestamp: 1751547635237
+- conda: https://conda.anaconda.org/conda-forge/noarch/alembic-1.17.2-pyhd8ed1ab_0.conda
+ sha256: 61f0bf071b04c02555e02d898e6ba9929807bd704b0d77c75bc47a1b3d4aed14
+ md5: b67a46343747e615a2a87b65b5b6feab
+ depends:
- mako
- - typing-extensions>=4.12
- - tomli ; python_full_version < '3.11'
- - tzdata ; extra == 'tz'
- requires_python: '>=3.10'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py313h78bf25f_0.conda
- sha256: dc26da204d67948118207322b563a010720497f14dd4b7b0a385bf69a73016ad
- md5: 65899d37680aab12f5e33ad07d15d1fd
- depends:
- - python >=3.13,<3.14.0a0
- - python_abi 3.13.* *_cp313
+ - python >=3.10
+ - sqlalchemy >=1.4.0
+ - tomli
+ - typing_extensions >=4.12
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/alembic?source=hash-mapping
+ size: 166818
+ timestamp: 1763216869997
+- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.1-hb03c661_0.conda
+ sha256: 224f1a55a9ba7e877bce980f14fc3e3c0f0fb6d3cbf3c5f1a8f5dd8391ce8bba
+ md5: bba37fb066adb90e1d876dff0fd5d09d
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: LGPL-2.1-or-later
+ license_family: GPL
+ purls: []
+ size: 585491
+ timestamp: 1766155792553
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.1-he30d5cf_0.conda
+ sha256: cb8c79ff99e2e36958e088278971cfec4aeed8e44084e968c906b7bbc3cd8de1
+ md5: 50a88426e78ae8eb7d52072ba2e8db21
+ depends:
+ - libgcc >=14
+ license: LGPL-2.1-or-later
+ license_family: GPL
+ purls: []
+ size: 615491
+ timestamp: 1766156819056
+- conda: https://conda.anaconda.org/conda-forge/linux-64/astroid-4.0.2-py312h7900ff3_0.conda
+ sha256: 314383c405003585d27883e7e9f3cc3973a1b29d625ba7feb6cf1b60ed94e704
+ md5: 01ddf9d3e4a39c3f032ba14ad91bdc82
+ depends:
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
license: LGPL-2.1-or-later
license_family: LGPL
purls:
- pkg:pypi/astroid?source=hash-mapping
- size: 518412
- timestamp: 1762775793423
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/astroid-4.0.2-py313hd81a959_0.conda
- sha256: 5cfde3eaf246f4a5fcc02a1b5517b1d68596e2ab85511bf9d4808c75a3810bbe
- md5: 523b4f671d9639932207ff812bac1870
- depends:
- - python >=3.13,<3.14.0a0
- - python >=3.13,<3.14.0a0 *_cp313
- - python_abi 3.13.* *_cp313
+ size: 509814
+ timestamp: 1762775882212
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/astroid-4.0.2-py312h996f985_0.conda
+ sha256: 675e3b58df90e5e6d69226c6cdbfba3cbcfcb987174cc879d09e0e2663657c6b
+ md5: 76a9d92d48fdbac2b80b43de8c6ac762
+ depends:
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
license: LGPL-2.1-or-later
license_family: LGPL
purls:
- pkg:pypi/astroid?source=hash-mapping
- size: 516800
- timestamp: 1762775967404
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/astroid-4.0.2-py313h8f79df9_0.conda
- sha256: a623b49fa4e8ea0de9a30fc391228c68d5e650c6a896f166ae1cd4d3bdf2fcc8
- md5: 3a4cbaca5012f9235d0b7066b90b2b46
- depends:
- - python >=3.13,<3.14.0a0
- - python >=3.13,<3.14.0a0 *_cp313
- - python_abi 3.13.* *_cp313
+ size: 508217
+ timestamp: 1762775868054
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/astroid-4.0.2-py312h81bd7bf_0.conda
+ sha256: d99d8544823925d21140481754f849b1599204a974c308acc3e43d6d4d893ea5
+ md5: ad0ba493bf5f9799c1875d511fcfab7e
+ depends:
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
license: LGPL-2.1-or-later
license_family: LGPL
purls:
- pkg:pypi/astroid?source=hash-mapping
- size: 520275
- timestamp: 1762776294541
-- pypi: https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl
- name: astunparse
- version: 1.6.3
- sha256: c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8
- requires_dist:
- - wheel>=0.23.0,<1.0
- - six>=1.6.1,<2.0
+ size: 511022
+ timestamp: 1762776240673
+- conda: https://conda.anaconda.org/conda-forge/noarch/astunparse-1.6.3-pyhd8ed1ab_3.conda
+ sha256: 7304f265f146235c34e24db310a94648aa306ca0b2a4a12042bf96da1881f99c
+ md5: d3f195dfdbbf736e4ec178bbec2a975c
+ depends:
+ - python >=3.9
+ - six >=1.6.1,<2.0
+ license: BSD-3-Clause AND PSF-2.0
+ purls:
+ - pkg:pypi/astunparse?source=hash-mapping
+ size: 18143
+ timestamp: 1736248194225
+- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py312h90b7ffd_0.conda
+ sha256: d77a24be15e283d83214121428290dbe55632a6e458378205b39c550afa008cf
+ md5: 5b8c55fed2e576dde4b0b33693a4fdb1
+ depends:
+ - python
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ - python_abi 3.12.* *_cp312
+ - zstd >=1.5.7,<1.6.0a0
+ license: BSD-3-Clause AND MIT AND EPL-2.0
+ purls:
+ - pkg:pypi/backports-zstd?source=hash-mapping
+ size: 237970
+ timestamp: 1767045004512
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py312h3d8e7d4_0.conda
+ sha256: 15ca235863f67ebbfa5a3c1cf1eb3f448ad4bafa9e9d1660996d90b406c2f5ca
+ md5: 342f2741b222094a78db95893ecc42f9
+ depends:
+ - python
+ - libgcc >=14
+ - python 3.12.* *_cpython
+ - zstd >=1.5.7,<1.6.0a0
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause AND MIT AND EPL-2.0
+ purls:
+ - pkg:pypi/backports-zstd?source=hash-mapping
+ size: 243175
+ timestamp: 1767044998908
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.3.0-py312h44dc372_0.conda
+ sha256: aee745bfca32f7073d3298157bbb2273d6d83383cb266840cf0a7862b3cd8efc
+ md5: c2d5961bfd98504b930e704426d16572
+ depends:
+ - python
+ - python 3.12.* *_cpython
+ - __osx >=11.0
+ - zstd >=1.5.7,<1.6.0a0
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause AND MIT AND EPL-2.0
+ purls:
+ - pkg:pypi/backports-zstd?source=hash-mapping
+ size: 241051
+ timestamp: 1767045000787
+- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda
+ sha256: e511644d691f05eb12ebe1e971fd6dc3ae55a4df5c253b4e1788b789bdf2dfa6
+ md5: 8ccf913aaba749a5496c17629d859ed1
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - brotli-bin 1.2.0 hb03c661_1
+ - libbrotlidec 1.2.0 hb03c661_1
+ - libbrotlienc 1.2.0 hb03c661_1
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 20103
+ timestamp: 1764017231353
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-1.2.0-hd651790_1.conda
+ sha256: 1fdee53dea5baa0b4d7ccd3bc0269e81017032c7cfe8843b6a0622eddf05714b
+ md5: 5c933384d588a06cd8dac78ca2864aab
+ depends:
+ - brotli-bin 1.2.0 he30d5cf_1
+ - libbrotlidec 1.2.0 he30d5cf_1
+ - libbrotlienc 1.2.0 he30d5cf_1
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 20145
+ timestamp: 1764017310011
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-1.2.0-h7d5ae5b_1.conda
+ sha256: 422ac5c91f8ef07017c594d9135b7ae068157393d2a119b1908c7e350938579d
+ md5: 48ece20aa479be6ac9a284772827d00c
+ depends:
+ - __osx >=11.0
+ - brotli-bin 1.2.0 hc919400_1
+ - libbrotlidec 1.2.0 hc919400_1
+ - libbrotlienc 1.2.0 hc919400_1
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 20237
+ timestamp: 1764018058424
+- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda
+ sha256: 64b137f30b83b1dd61db6c946ae7511657eead59fdf74e84ef0ded219605aa94
+ md5: af39b9a8711d4a8d437b52c1d78eb6a1
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libbrotlidec 1.2.0 hb03c661_1
+ - libbrotlienc 1.2.0 hb03c661_1
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 21021
+ timestamp: 1764017221344
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-bin-1.2.0-he30d5cf_1.conda
+ sha256: cffd260d3b1527ff8c1d29f00e10f4e1d4bccbe4d5e605c23af68453cf78d32b
+ md5: b31f6f3a888c3f8f4c5a9dafc2575187
+ depends:
+ - libbrotlidec 1.2.0 he30d5cf_1
+ - libbrotlienc 1.2.0 he30d5cf_1
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 20758
+ timestamp: 1764017301339
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-bin-1.2.0-hc919400_1.conda
+ sha256: e2d142052a83ff2e8eab3fe68b9079cad80d109696dc063a3f92275802341640
+ md5: 377d015c103ad7f3371be1777f8b584c
+ depends:
+ - __osx >=11.0
+ - libbrotlidec 1.2.0 hc919400_1
+ - libbrotlienc 1.2.0 hc919400_1
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 18628
+ timestamp: 1764018033635
+- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda
+ sha256: 49df13a1bb5e388ca0e4e87022260f9501ed4192656d23dc9d9a1b4bf3787918
+ md5: 64088dffd7413a2dd557ce837b4cbbdb
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - libbrotlicommon 1.2.0 hb03c661_1
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/brotli?source=compressed-mapping
+ size: 368300
+ timestamp: 1764017300621
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py312hac7b6a9_1.conda
+ sha256: aa14d1f26a1d4ed3a735281beb20129b9ba4670fed688045ac71f4119aeed7e6
+ md5: d64147176625536a8024e26577c5e894
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - libbrotlicommon 1.2.0 he30d5cf_1
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/brotli?source=hash-mapping
+ size: 373800
+ timestamp: 1764017545385
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda
+ sha256: 6178775a86579d5e8eec6a7ab316c24f1355f6c6ccbe84bb341f342f1eda2440
+ md5: 311fcf3f6a8c4eb70f912798035edd35
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - libbrotlicommon 1.2.0 hc919400_1
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/brotli?source=hash-mapping
+ size: 359503
+ timestamp: 1764018572368
- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda
sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5
md5: 51a19bba1b8ebfb60df25cde030b7ebc
@@ -508,6 +1086,37 @@ packages:
purls: []
size: 125061
timestamp: 1757437486465
+- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda
+ sha256: cc9accf72fa028d31c2a038460787751127317dcfa991f8d1f1babf216bb454e
+ md5: 920bb03579f15389b9e512095ad995b7
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 207882
+ timestamp: 1765214722852
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda
+ sha256: 7ec8a68efe479e2e298558cbc2e79d29430d5c7508254268818c0ae19b206519
+ md5: 1dfbec0d08f112103405756181304c16
+ depends:
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 217215
+ timestamp: 1765214743735
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda
+ sha256: 2995f2aed4e53725e5efbc28199b46bf311c3cab2648fc4f10c2227d6d5fa196
+ md5: bcb3cba70cf1eec964a03b4ba7775f01
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 180327
+ timestamp: 1765215064054
- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.11.12-hbd8a1cb_0.conda
sha256: b986ba796d42c9d3265602bc038f6f5264095702dd546c14bc684e60c385e773
md5: f0991f0f84902f6b6009b4d2350a83aa
@@ -517,26 +1126,100 @@ packages:
purls: []
size: 152432
timestamp: 1762967197890
-- pypi: https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl
- name: certifi
- version: 2025.11.12
- sha256: 97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: charset-normalizer
- version: 3.4.4
- sha256: 6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl
- name: charset-normalizer
- version: 3.4.4
- sha256: e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- name: charset-normalizer
- version: 3.4.4
- sha256: a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894
- requires_python: '>=3.7'
+- conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2
+ noarch: python
+ sha256: 561e6660f26c35d137ee150187d89767c988413c978e1b712d53f27ddf70ea17
+ md5: 9b347a7ec10940d3f7941ff6c460b551
+ depends:
+ - cached_property >=1.5.2,<1.5.3.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 4134
+ timestamp: 1615209571450
+- conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2
+ sha256: 6dbf7a5070cc43d90a1e4c2ec0c541c69d8e30a0e25f50ce9f6e4a432e42c5d7
+ md5: 576d629e47797577ab0f1b351297ef4a
+ depends:
+ - python >=3.6
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/cached-property?source=hash-mapping
+ size: 11065
+ timestamp: 1615209567874
+- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-h3394656_0.conda
+ sha256: 3bd6a391ad60e471de76c0e9db34986c4b5058587fbf2efa5a7f54645e28c2c7
+ md5: 09262e66b19567aff4f592fb53b28760
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - fontconfig >=2.15.0,<3.0a0
+ - fonts-conda-ecosystem
+ - freetype >=2.12.1,<3.0a0
+ - icu >=75.1,<76.0a0
+ - libexpat >=2.6.4,<3.0a0
+ - libgcc >=13
+ - libglib >=2.82.2,<3.0a0
+ - libpng >=1.6.47,<1.7.0a0
+ - libstdcxx >=13
+ - libxcb >=1.17.0,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - pixman >=0.44.2,<1.0a0
+ - xorg-libice >=1.1.2,<2.0a0
+ - xorg-libsm >=1.2.5,<2.0a0
+ - xorg-libx11 >=1.8.11,<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: []
+ size: 978114
+ timestamp: 1741554591855
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h83712da_0.conda
+ sha256: 37cfff940d2d02259afdab75eb2dbac42cf830adadee78d3733d160a1de2cc66
+ md5: cd55953a67ec727db5dc32b167201aa6
+ depends:
+ - fontconfig >=2.15.0,<3.0a0
+ - fonts-conda-ecosystem
+ - freetype >=2.12.1,<3.0a0
+ - icu >=75.1,<76.0a0
+ - libexpat >=2.6.4,<3.0a0
+ - libgcc >=13
+ - libglib >=2.82.2,<3.0a0
+ - libpng >=1.6.47,<1.7.0a0
+ - libstdcxx >=13
+ - libxcb >=1.17.0,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - pixman >=0.44.2,<1.0a0
+ - xorg-libice >=1.1.2,<2.0a0
+ - xorg-libsm >=1.2.5,<2.0a0
+ - xorg-libx11 >=1.8.11,<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: []
+ size: 966667
+ timestamp: 1741554768968
+- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2025.11.12-pyhd8ed1ab_0.conda
+ sha256: 083a2bdad892ccf02b352ecab38ee86c3e610ba9a4b11b073ea769d55a115d32
+ md5: 96a02a5c1a65470a7e4eedb644c872fd
+ depends:
+ - python >=3.10
+ license: ISC
+ purls:
+ - pkg:pypi/certifi?source=compressed-mapping
+ size: 157131
+ timestamp: 1762976260320
+- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.4-pyhd8ed1ab_0.conda
+ sha256: b32f8362e885f1b8417bac2b3da4db7323faa12d5db62b7fd6691c02d60d6f59
+ md5: a22d1fd9bf98827e280a02875d9a007a
+ depends:
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/charset-normalizer?source=hash-mapping
+ size: 50965
+ timestamp: 1760437331772
- pypi: https://files.pythonhosted.org/packages/b7/9f/d73dfb85d7a5b1a56a99adc50f2074029468168c970ff5daeade4ad819e4/choreographer-1.2.1-py3-none-any.whl
name: choreographer
version: 1.2.1
@@ -545,13 +1228,19 @@ packages:
- logistro>=2.0.1
- simplejson>=3.19.3
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl
- name: click
- version: 8.3.1
- sha256: 981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6
- requires_dist:
- - colorama ; sys_platform == 'win32'
- requires_python: '>=3.10'
+- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda
+ sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715
+ md5: ea8a6c3256897cc31263de9f455e25d9
+ depends:
+ - python >=3.10
+ - __unix
+ - python
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/click?source=hash-mapping
+ size: 97676
+ timestamp: 1764518652276
- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287
md5: 962b9857ee8e7018c22f2776ffa0b2d7
@@ -563,158 +1252,203 @@ packages:
- pkg:pypi/colorama?source=hash-mapping
size: 27011
timestamp: 1733218222191
-- pypi: https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl
- name: coloredlogs
- version: 15.0.1
- sha256: 612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934
- requires_dist:
- - humanfriendly>=9.1
- - capturer>=2.4 ; extra == 'cron'
- requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*'
-- pypi: https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl
- name: colorlog
- version: 6.10.1
- sha256: 2d7e8348291948af66122cff006c9f8da6255d224e7cf8e37d8de2df3bad8c9c
- requires_dist:
- - colorama ; sys_platform == 'win32'
- - black ; extra == 'development'
- - flake8 ; extra == 'development'
- - mypy ; extra == 'development'
- - pytest ; extra == 'development'
- - types-colorama ; extra == 'development'
- requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: contourpy
- version: 1.3.3
- sha256: 4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9
- requires_dist:
- - numpy>=1.25
- - furo ; extra == 'docs'
- - sphinx>=7.2 ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - bokeh ; extra == 'bokeh'
- - selenium ; extra == 'bokeh'
- - contourpy[bokeh,docs] ; extra == 'mypy'
- - bokeh ; extra == 'mypy'
- - docutils-stubs ; extra == 'mypy'
- - mypy==1.17.0 ; extra == 'mypy'
- - types-pillow ; extra == 'mypy'
- - contourpy[test-no-images] ; extra == 'test'
- - matplotlib ; extra == 'test'
- - pillow ; extra == 'test'
- - pytest ; extra == 'test-no-images'
- - pytest-cov ; extra == 'test-no-images'
- - pytest-rerunfailures ; extra == 'test-no-images'
- - pytest-xdist ; extra == 'test-no-images'
- - wurlitzer ; extra == 'test-no-images'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- name: contourpy
- version: 1.3.3
- sha256: 348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286
- requires_dist:
- - numpy>=1.25
- - furo ; extra == 'docs'
- - sphinx>=7.2 ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - bokeh ; extra == 'bokeh'
- - selenium ; extra == 'bokeh'
- - contourpy[bokeh,docs] ; extra == 'mypy'
- - bokeh ; extra == 'mypy'
- - docutils-stubs ; extra == 'mypy'
- - mypy==1.17.0 ; extra == 'mypy'
- - types-pillow ; extra == 'mypy'
- - contourpy[test-no-images] ; extra == 'test'
- - matplotlib ; extra == 'test'
- - pillow ; extra == 'test'
- - pytest ; extra == 'test-no-images'
- - pytest-cov ; extra == 'test-no-images'
- - pytest-rerunfailures ; extra == 'test-no-images'
- - pytest-xdist ; extra == 'test-no-images'
- - wurlitzer ; extra == 'test-no-images'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl
- name: contourpy
- version: 1.3.3
- sha256: d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1
- requires_dist:
- - numpy>=1.25
- - furo ; extra == 'docs'
- - sphinx>=7.2 ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - bokeh ; extra == 'bokeh'
- - selenium ; extra == 'bokeh'
- - contourpy[bokeh,docs] ; extra == 'mypy'
- - bokeh ; extra == 'mypy'
- - docutils-stubs ; extra == 'mypy'
- - mypy==1.17.0 ; extra == 'mypy'
- - types-pillow ; extra == 'mypy'
- - contourpy[test-no-images] ; extra == 'test'
- - matplotlib ; extra == 'test'
- - pillow ; extra == 'test'
- - pytest ; extra == 'test-no-images'
- - pytest-cov ; extra == 'test-no-images'
- - pytest-rerunfailures ; extra == 'test-no-images'
- - pytest-xdist ; extra == 'test-no-images'
- - wurlitzer ; extra == 'test-no-images'
- requires_python: '>=3.11'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.13.1-py313h3dea7bd_0.conda
- sha256: 4275280f4fcef6cd0a0e5cd236120d7454a11390dd4c271378bf90bc563f6780
- md5: 82315acb438e857f809f556e2dcdb822
- depends:
- - __glibc >=2.17,<3.0.a0
- - libgcc >=14
- - python >=3.13,<3.14.0a0
- - python_abi 3.13.* *_cp313
+- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda
+ sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680
+ md5: b866ff7007b934d564961066c8195983
+ depends:
+ - humanfriendly >=9.1
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/coloredlogs?source=hash-mapping
+ size: 43758
+ timestamp: 1733928076798
+- conda: https://conda.anaconda.org/conda-forge/noarch/colorlog-6.10.1-pyh707e725_0.conda
+ sha256: 3b1dfc03f86d5eeec695134d307a236fb9b67ed3f35c09fd1fcc760c5e4039da
+ md5: 33e96df3785bf61676ffee387e5a19e5
+ depends:
+ - __unix
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/colorlog?source=hash-mapping
+ size: 16410
+ timestamp: 1760645097806
+- conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py312hd9148b4_3.conda
+ sha256: e173ea96fb135b233c7f57c35c0d07f7adc50ebacf814550f3daf1c7ba2ed51e
+ md5: 86cf7a7d861b79d38e3f0e5097e4965b
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.25
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/contourpy?source=hash-mapping
+ size: 295243
+ timestamp: 1762525427240
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/contourpy-1.3.3-py312h4f740d2_3.conda
+ sha256: e7755fae79a06a09aea34e1f6e48197b1aad323ef58dbc6634eaead321e221f6
+ md5: 9e16abf6b2f65b807ad95a629c2fa188
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.25
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/contourpy?source=hash-mapping
+ size: 306524
+ timestamp: 1762525589118
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/contourpy-1.3.3-py312h84eede6_3.conda
+ sha256: ee6a2497f2d9aff6ec53b6998a37c546916b79118e386bb90a7cb1f389d35197
+ md5: e3fbe173dea7137a6d766cbacf697df2
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ - numpy >=1.25
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/contourpy?source=hash-mapping
+ size: 258388
+ timestamp: 1762525877844
+- conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.13.1-py312h8a5da7c_0.conda
+ sha256: dd832f036d8aefed827b79f9b5fab94b807f97979c5339c0deebeceab4c032b5
+ md5: eafe0b486a7910e4a6973029c80d437f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
- tomli
license: Apache-2.0
license_family: APACHE
purls:
- pkg:pypi/coverage?source=hash-mapping
- size: 393234
- timestamp: 1766951417242
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.13.1-py313hfa222a2_0.conda
- sha256: 08b106da86fb07a8b97a0d7c111ce094cd240831701322fe459c1cc6b6940734
- md5: 2673bb6f13a235122237b3c321b5dcbb
+ size: 385419
+ timestamp: 1766951277302
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/coverage-7.13.1-py312hd077ced_0.conda
+ sha256: 3b24ae226394187170259acee8ddb332f049ac32616d81cf5586e261ed1c9c27
+ md5: fdd041d3d6c17f71337e7e3c1a12b3d9
depends:
- libgcc >=14
- - python >=3.13,<3.14.0a0
- - python_abi 3.13.* *_cp313
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
- tomli
license: Apache-2.0
license_family: APACHE
purls:
- pkg:pypi/coverage?source=hash-mapping
- size: 393945
- timestamp: 1766952440036
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/coverage-7.13.1-py313h65a2061_0.conda
- sha256: 46e4af43bd60580fda7955cc6c21b3a40465ef25a98c2a256419dc74caae56b0
- md5: 3283d95f985c7f293cb13bb7e33500a5
+ size: 386210
+ timestamp: 1766952411552
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/coverage-7.13.1-py312h04c11ed_0.conda
+ sha256: 1d146c94ff86121caf81c4fa34246369b8a34b94a7bc77bc3a5029b4fad1f117
+ md5: 642464ee9b266754a47f664e6e0614f3
depends:
- __osx >=11.0
- - python >=3.13,<3.14.0a0
- - python >=3.13,<3.14.0a0 *_cp313
- - python_abi 3.13.* *_cp313
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
- tomli
license: Apache-2.0
license_family: APACHE
purls:
- pkg:pypi/coverage?source=hash-mapping
- size: 393649
- timestamp: 1766951606379
-- pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl
- name: cycler
- version: 0.12.1
- sha256: 85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30
- requires_dist:
- - ipython ; extra == 'docs'
- - matplotlib ; extra == 'docs'
- - numpydoc ; extra == 'docs'
- - sphinx ; extra == 'docs'
- - pytest ; extra == 'tests'
- - pytest-cov ; extra == 'tests'
- - pytest-xdist ; extra == 'tests'
- requires_python: '>=3.8'
+ size: 383752
+ timestamp: 1766951525579
+- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda
+ noarch: generic
+ sha256: b88c76a6d6b45378552ccfd9e88b2a073161fe83fd1294c8fa103ffd32f7934a
+ md5: 99d689ccc1a360639eec979fd7805be9
+ depends:
+ - python >=3.12,<3.13.0a0
+ - python_abi * *_cp312
+ license: Python-2.0
+ purls: []
+ size: 45767
+ timestamp: 1761175217281
+- 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
+ size: 14778
+ timestamp: 1764466758386
+- conda: https://conda.anaconda.org/conda-forge/linux-64/cyrus-sasl-2.1.28-hd9c7081_0.conda
+ sha256: ee09ad7610c12c7008262d713416d0b58bf365bc38584dce48950025850bdf3f
+ md5: cae723309a49399d2949362f4ab5c9e4
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=13
+ - libntlm >=1.8,<2.0a0
+ - libstdcxx >=13
+ - libxcrypt >=4.4.36
+ - openssl >=3.5.0,<4.0a0
+ license: BSD-3-Clause-Attribution
+ license_family: BSD
+ purls: []
+ size: 209774
+ timestamp: 1750239039316
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cyrus-sasl-2.1.28-h6c5dea3_0.conda
+ sha256: 87b603b76b05e9be749a2616582bfb907e06e7851285bdd78f9ddaaa732d7bc7
+ md5: b6d06b46e791add99cc39fbbc34530d5
+ depends:
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=13
+ - libntlm
+ - libstdcxx >=13
+ - libxcrypt >=4.4.36
+ - openssl >=3.5.0,<4.0a0
+ license: BSD-3-Clause-Attribution
+ license_family: BSD
+ purls: []
+ size: 227295
+ timestamp: 1750239141751
+- 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: []
+ size: 447649
+ timestamp: 1764536047944
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/dbus-1.16.2-h70963c4_1.conda
+ sha256: 3af801577431af47c0b72a82bb93c654f03072dece0a2a6f92df8a6802f52a22
+ md5: a4b6b82427d15f0489cef0df2d82f926
+ depends:
+ - libstdcxx >=14
+ - libgcc >=14
+ - libglib >=2.86.2,<3.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - libexpat >=2.7.3,<3.0a0
+ license: AFL-2.1 OR GPL-2.0-or-later
+ purls: []
+ size: 480416
+ timestamp: 1764536098891
- conda: https://conda.anaconda.org/conda-forge/noarch/dill-0.4.0-pyhcf101f3_1.conda
sha256: c0c91bd91e59940091cec1760db51a82a58e9c64edf4b808bd2da94201ccfdb4
md5: eec5b361dbbaa69dba05050977a414b0
@@ -727,6 +1461,29 @@ packages:
- pkg:pypi/dill?source=hash-mapping
size: 94889
timestamp: 1764517905571
+- 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: []
+ size: 71809
+ timestamp: 1765193127016
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/double-conversion-3.4.0-hfae3067_0.conda
+ sha256: a636dfd17adc2a859cbdfce97e449e338b02a9f099c6dc0941c9f26bf448cca9
+ md5: 9fd794eaf983eabf975ead524540b4be
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 71905
+ timestamp: 1765194538141
- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144
md5: 8e662bd460bda79b1ea39194e3c4c9ab
@@ -738,3045 +1495,6805 @@ packages:
- pkg:pypi/exceptiongroup?source=hash-mapping
size: 21333
timestamp: 1763918099466
-- pypi: https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl
- name: flatbuffers
- version: 25.12.19
- sha256: 7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4
-- pypi: https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl
- name: fonttools
- version: 4.61.1
- sha256: 8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c
- requires_dist:
- - lxml>=4.0 ; extra == 'lxml'
- - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
- - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff'
- - zopfli>=0.1.4 ; extra == 'woff'
- - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode'
- - lz4>=1.7.4.2 ; extra == 'graphite'
- - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable'
- - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable'
- - pycairo ; extra == 'interpolatable'
- - matplotlib ; extra == 'plot'
- - sympy ; extra == 'symfont'
- - xattr ; sys_platform == 'darwin' and extra == 'type1'
- - skia-pathops>=0.5.0 ; extra == 'pathops'
- - uharfbuzz>=0.45.0 ; extra == 'repacker'
- - lxml>=4.0 ; extra == 'all'
- - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all'
- - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all'
- - zopfli>=0.1.4 ; extra == 'all'
- - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all'
- - lz4>=1.7.4.2 ; extra == 'all'
- - scipy ; platform_python_implementation != 'PyPy' and extra == 'all'
- - munkres ; platform_python_implementation == 'PyPy' and extra == 'all'
- - pycairo ; extra == 'all'
- - matplotlib ; extra == 'all'
- - sympy ; extra == 'all'
- - xattr ; sys_platform == 'darwin' and extra == 'all'
- - skia-pathops>=0.5.0 ; extra == 'all'
- - uharfbuzz>=0.45.0 ; extra == 'all'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
- name: fonttools
- version: 4.61.1
- sha256: 64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5
- requires_dist:
- - lxml>=4.0 ; extra == 'lxml'
- - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
- - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff'
- - zopfli>=0.1.4 ; extra == 'woff'
- - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode'
- - lz4>=1.7.4.2 ; extra == 'graphite'
- - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable'
- - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable'
- - pycairo ; extra == 'interpolatable'
- - matplotlib ; extra == 'plot'
- - sympy ; extra == 'symfont'
- - xattr ; sys_platform == 'darwin' and extra == 'type1'
- - skia-pathops>=0.5.0 ; extra == 'pathops'
- - uharfbuzz>=0.45.0 ; extra == 'repacker'
- - lxml>=4.0 ; extra == 'all'
- - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all'
- - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all'
- - zopfli>=0.1.4 ; extra == 'all'
- - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all'
- - lz4>=1.7.4.2 ; extra == 'all'
- - scipy ; platform_python_implementation != 'PyPy' and extra == 'all'
- - munkres ; platform_python_implementation == 'PyPy' and extra == 'all'
- - pycairo ; extra == 'all'
- - matplotlib ; extra == 'all'
- - sympy ; extra == 'all'
- - xattr ; sys_platform == 'darwin' and extra == 'all'
- - skia-pathops>=0.5.0 ; extra == 'all'
- - uharfbuzz>=0.45.0 ; extra == 'all'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: fonttools
- version: 4.61.1
- sha256: 4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd
- requires_dist:
- - lxml>=4.0 ; extra == 'lxml'
- - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff'
- - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff'
- - zopfli>=0.1.4 ; extra == 'woff'
- - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'unicode'
- - lz4>=1.7.4.2 ; extra == 'graphite'
- - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable'
- - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable'
- - pycairo ; extra == 'interpolatable'
- - matplotlib ; extra == 'plot'
- - sympy ; extra == 'symfont'
- - xattr ; sys_platform == 'darwin' and extra == 'type1'
- - skia-pathops>=0.5.0 ; extra == 'pathops'
- - uharfbuzz>=0.45.0 ; extra == 'repacker'
- - lxml>=4.0 ; extra == 'all'
- - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all'
- - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all'
- - zopfli>=0.1.4 ; extra == 'all'
- - unicodedata2>=17.0.0 ; python_full_version < '3.15' and extra == 'all'
- - lz4>=1.7.4.2 ; extra == 'all'
- - scipy ; platform_python_implementation != 'PyPy' and extra == 'all'
- - munkres ; platform_python_implementation == 'PyPy' and extra == 'all'
- - pycairo ; extra == 'all'
- - matplotlib ; extra == 'all'
- - sympy ; extra == 'all'
- - xattr ; sys_platform == 'darwin' and extra == 'all'
- - skia-pathops>=0.5.0 ; extra == 'all'
- - uharfbuzz>=0.45.0 ; extra == 'all'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/1d/33/f1c6a276de27b7d7339a34749cc33fa87f077f921969c47185d34a887ae2/gast-0.7.0-py3-none-any.whl
- name: gast
- version: 0.7.0
- sha256: 99cbf1365633a74099f69c59bd650476b96baa5ef196fec88032b00b31ba36f7
- requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*'
-- pypi: https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl
- name: google-pasta
- version: 0.2.0
- sha256: b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed
- requires_dist:
- - six
-- pypi: https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- name: greenlet
- version: 3.3.0
- sha256: 9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808
- requires_dist:
- - sphinx ; extra == 'docs'
- - furo ; extra == 'docs'
- - objgraph ; extra == 'test'
- - psutil ; extra == 'test'
- - setuptools ; extra == 'test'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- name: greenlet
- version: 3.3.0
- sha256: 087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527
- requires_dist:
- - sphinx ; extra == 'docs'
- - furo ; extra == 'docs'
- - objgraph ; extra == 'test'
- - psutil ; extra == 'test'
- - setuptools ; extra == 'test'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- name: grpcio
- version: 1.76.0
- sha256: 61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae
- requires_dist:
- - typing-extensions~=4.12
- - grpcio-tools>=1.76.0 ; extra == 'protobuf'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl
- name: grpcio
- version: 1.76.0
- sha256: 45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468
- requires_dist:
- - typing-extensions~=4.12
- - grpcio-tools>=1.76.0 ; extra == 'protobuf'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- name: grpcio
- version: 1.76.0
- sha256: 83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3
- requires_dist:
- - typing-extensions~=4.12
- - grpcio-tools>=1.76.0 ; extra == 'protobuf'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/31/96/ba99a003c763998035b0de4c299598125df5fc6c9ccf834f152ddd60e0fb/h5py-3.15.1-cp313-cp313-macosx_11_0_arm64.whl
- name: h5py
- version: 3.15.1
- sha256: ab2219dbc6fcdb6932f76b548e2b16f34a1f52b7666e998157a4dfc02e2c4123
- requires_dist:
- - numpy>=1.21.2
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/6a/c2/fc6375d07ea3962df7afad7d863fe4bde18bb88530678c20d4c90c18de1d/h5py-3.15.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- name: h5py
- version: 3.15.1
- sha256: d8cb02c3a96255149ed3ac811eeea25b655d959c6dd5ce702c9a95ff11859eb5
- requires_dist:
- - numpy>=1.21.2
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/d9/69/4402ea66272dacc10b298cca18ed73e1c0791ff2ae9ed218d3859f9698ac/h5py-3.15.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: h5py
- version: 3.15.1
- sha256: 121b2b7a4c1915d63737483b7bff14ef253020f617c2fb2811f67a4bed9ac5e8
- requires_dist:
- - numpy>=1.21.2
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl
- name: humanfriendly
- version: '10.0'
- sha256: 1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477
- requires_dist:
- - monotonic ; python_full_version == '2.7.*'
- - pyreadline ; python_full_version < '3.8' and sys_platform == 'win32'
- - pyreadline3 ; python_full_version >= '3.8' and sys_platform == 'win32'
- requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*'
-- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- name: idna
- version: '3.11'
- sha256: 771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea
- requires_dist:
- - ruff>=0.6.2 ; extra == 'all'
- - mypy>=1.11.2 ; extra == 'all'
- - pytest>=8.3.2 ; extra == 'all'
- - flake8>=7.1.1 ; extra == 'all'
- requires_python: '>=3.8'
-- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
- sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745
- md5: 63ccfdc3a3ce25b027b8767eb722fca8
+- conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-25.2.10-hb7832b1_0.conda
+ sha256: 0e58114d0e16bc89b94ef9068558e304d2eccae5dbaa55b955274ea60da81dfd
+ md5: 279ba9719d1afc81538d8260f31e42a0
depends:
- - python >=3.9
- - zipp >=3.20
- - python
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libstdcxx >=13
license: Apache-2.0
license_family: APACHE
- purls:
- - pkg:pypi/importlib-metadata?source=hash-mapping
- size: 34641
- timestamp: 1747934053147
-- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
- sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19
- md5: 9614359868482abba1bd15ce465e3c42
- depends:
- - python >=3.10
- license: MIT
- license_family: MIT
- purls:
- - pkg:pypi/iniconfig?source=compressed-mapping
- size: 13387
- timestamp: 1760831448842
-- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
- sha256: 13b0005877f553eb2e5c50447c9d0047e7257124ec2d1569d7dad35697790237
- md5: 55a61979242077b2cc377c74326ea9f0
- depends:
- - importlib-metadata >=4.6.0
- - python >=3.10,<4.0
- license: MIT
- license_family: MIT
- purls:
- - pkg:pypi/isort?source=hash-mapping
- size: 74876
- timestamp: 1760192714356
-- pypi: https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl
- name: joblib
- version: 1.5.3
- sha256: 5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
- name: kaleido
- version: 1.2.0
- sha256: c27ed82b51df6b923d0e656feac221343a0dbcd2fb9bc7e6b1db97f61e9a1513
- requires_dist:
- - choreographer>=1.1.1
- - logistro>=1.0.8
- - orjson>=3.10.15
- - packaging
- - pytest-timeout>=2.4.0
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/15/d2/c6734cbf15288d75722ed3eb9d8ebf9204e48379c08160fd40fcd58a0c8b/keras-3.13.0-py3-none-any.whl
- name: keras
- version: 3.13.0
- sha256: 096793e2be6230816f3f7e030370e66c0f4a89707c59bf2d8fad3ca33869bd1c
- requires_dist:
- - absl-py
- - numpy
- - rich
- - namex
- - h5py
- - optree
- - ml-dtypes
- - packaging
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl
- name: kiwisolver
- version: 1.4.9
- sha256: 1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- name: kiwisolver
- version: 1.4.9
- sha256: 5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- name: kiwisolver
- version: 1.4.9
- sha256: b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098
- requires_python: '>=3.10'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_104.conda
- sha256: 9e191baf2426a19507f1d0a17be0fdb7aa155cdf0f61d5a09c808e0a69464312
- md5: a6abd2796fc332536735f68ba23f7901
+ purls: []
+ size: 1539958
+ timestamp: 1747130572350
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.12.23-hb76e14f_0.conda
+ sha256: a64c85e186d1ad922ce0263816953d6efedca85c0ddb4650d3a89ae7f9c92fe2
+ md5: 9308cc23dde88cee8bb791d68a54c106
depends:
- - __glibc >=2.17,<3.0.a0
- - zstd >=1.5.7,<1.6.0a0
- constrains:
- - binutils_impl_linux-64 2.45
- license: GPL-3.0-only
- license_family: GPL
+ - libgcc >=13
+ - libstdcxx >=13
+ license: Apache-2.0
+ license_family: APACHE
purls: []
- size: 725545
- timestamp: 1764007826689
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45-default_h1979696_104.conda
- sha256: 7a13072581fa23f658a04f62f62c4677c57d3c9696fbc01cc954a88fc354b44d
- md5: 28035705fe0c977ea33963489cd008ad
+ size: 1377360
+ timestamp: 1736587365110
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.12.23-h28594ff_0.conda
+ sha256: 3eb3d471cda99c6b1de152078f784cac2f498620af1eeb2cc0f3407987810c55
+ md5: b7b7a7a8a69ec7f3a7fccfbdab2352c0
depends:
- - zstd >=1.5.7,<1.6.0a0
- constrains:
- - binutils_impl_linux-aarch64 2.45
- license: GPL-3.0-only
- license_family: GPL
+ - __osx >=11.0
+ - libcxx >=18
+ license: Apache-2.0
+ license_family: APACHE
purls: []
- size: 875534
- timestamp: 1764007911054
-- pypi: https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl
- name: libclang
- version: 18.1.1
- sha256: c533091d8a3bbf7460a00cb6c1a71da93bffe148f172c7d03b1c31fbf8aa2a0b
-- pypi: https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl
- name: libclang
- version: 18.1.1
- sha256: 54dda940a4a0491a9d1532bf071ea3ef26e6dbaf03b5000ed94dd7174e8f9592
-- pypi: https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl
- name: libclang
- version: 18.1.1
- sha256: 0b2e143f0fac830156feb56f9231ff8338c20aecfe72b4ffe96f19e5a1dbb69a
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda
- sha256: 1e1b08f6211629cbc2efe7a5bca5953f8f6b3cae0eeb04ca4dacee1bd4e2db2f
- md5: 8b09ae86839581147ef2e5c5e229d164
+ size: 1281858
+ timestamp: 1736587423115
+- 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: []
+ 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: []
+ 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: []
+ 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: []
+ size: 1620504
+ timestamp: 1727511233259
+- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.15.0-h7e30c49_1.conda
+ sha256: 7093aa19d6df5ccb6ca50329ef8510c6acb6b0d8001191909397368b65b02113
+ md5: 8f5b0b297b59e1ac160ad4beec99dbee
depends:
- __glibc >=2.17,<3.0.a0
- - libgcc >=14
- constrains:
- - expat 2.7.3.*
+ - freetype >=2.12.1,<3.0a0
+ - libexpat >=2.6.3,<3.0a0
+ - libgcc >=13
+ - libuuid >=2.38.1,<3.0a0
+ - libzlib >=1.3.1,<2.0a0
license: MIT
license_family: MIT
purls: []
- size: 76643
- timestamp: 1763549731408
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.3-hfae3067_0.conda
- sha256: cc2581a78315418cc2e0bb2a273d37363203e79cefe78ba6d282fed546262239
- md5: b414e36fbb7ca122030276c75fa9c34a
+ size: 265599
+ timestamp: 1730283881107
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.15.0-h8dda3cd_1.conda
+ sha256: fe023bb8917c8a3138af86ef537b70c8c5d60c44f93946a87d1e8bb1a6634b55
+ md5: 112b71b6af28b47c624bcbeefeea685b
depends:
- - libgcc >=14
- constrains:
- - expat 2.7.3.*
+ - freetype >=2.12.1,<3.0a0
+ - libexpat >=2.6.3,<3.0a0
+ - libgcc >=13
+ - libuuid >=2.38.1,<3.0a0
+ - libzlib >=1.3.1,<2.0a0
license: MIT
license_family: MIT
purls: []
- size: 76201
- timestamp: 1763549910086
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
- sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98
- md5: b79875dbb5b1db9a4a22a4520f918e1a
+ size: 277832
+ timestamp: 1730284967179
+- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2
+ sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61
+ md5: fee5683a3f04bd15cbd8318b096a27ab
depends:
- - __osx >=11.0
- constrains:
- - expat 2.7.3.*
- license: MIT
- license_family: MIT
+ - fonts-conda-forge
+ license: BSD-3-Clause
+ license_family: BSD
purls: []
- size: 67800
- timestamp: 1763549994166
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda
- sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54
- md5: 35f29eec58405aaf55e01cb470d8c26a
+ 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: []
+ size: 4059
+ timestamp: 1762351264405
+- conda: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.61.1-py312h8a5da7c_0.conda
+ sha256: c73cd238e0f6b2183c5168b64aa35a7eb66bb145192a9b26bb9041a4152844a3
+ md5: 3bf8fb959dc598c67dac0430b4aff57a
depends:
- __glibc >=2.17,<3.0.a0
+ - brotli
- libgcc >=14
+ - munkres
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - unicodedata2 >=15.1.0
license: MIT
license_family: MIT
- purls: []
- size: 57821
- timestamp: 1760295480630
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-hd65408f_0.conda
- sha256: 6c3332e78a975e092e54f87771611db81dcb5515a3847a3641021621de76caea
- md5: 0c5ad486dcfb188885e3cf8ba209b97b
+ purls:
+ - pkg:pypi/fonttools?source=hash-mapping
+ size: 2932702
+ timestamp: 1765632761555
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fonttools-4.61.1-py312ha4530ae_0.conda
+ sha256: 2274586cc2863f249f0d843b343897f6448e4e0ccceb51a1af6673de2ebd1c02
+ md5: 815d984410c54cf5186fbb6f2ff13628
depends:
+ - brotli
- libgcc >=14
+ - munkres
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - unicodedata2 >=15.1.0
license: MIT
license_family: MIT
- purls: []
- size: 55586
- timestamp: 1760295405021
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
- sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f
- md5: 411ff7cd5d1472bba0f55c0faf04453b
+ purls:
+ - pkg:pypi/fonttools?source=hash-mapping
+ size: 2901753
+ timestamp: 1765632735926
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fonttools-4.61.1-py312h5748b74_0.conda
+ sha256: d87752e84621f90e9350262200fef55f054472f7779323f51717b557208e2a16
+ md5: c14625bf00c41c00cea174f459287fc4
depends:
- __osx >=11.0
+ - brotli
+ - munkres
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - unicodedata2 >=15.1.0
license: MIT
license_family: MIT
- purls: []
- size: 40251
- timestamp: 1760295839166
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda
- sha256: 6eed58051c2e12b804d53ceff5994a350c61baf117ec83f5f10c953a3f311451
- md5: 6d0363467e6ed84f11435eb309f2ff06
+ purls:
+ - pkg:pypi/fonttools?source=hash-mapping
+ size: 2859891
+ timestamp: 1765633073562
+- conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.1-ha770c72_0.conda
+ sha256: bf8e4dffe46f7d25dc06f31038cacb01672c47b9f45201f065b0f4d00ab0a83e
+ md5: 4afc585cd97ba8a23809406cd8a9eda8
depends:
- - __glibc >=2.17,<3.0.a0
- - _openmp_mutex >=4.5
- constrains:
- - libgcc-ng ==15.2.0=*_16
- - libgomp 15.2.0 he0feb66_16
- license: GPL-3.0-only WITH GCC-exception-3.1
- license_family: GPL
+ - libfreetype 2.14.1 ha770c72_0
+ - libfreetype6 2.14.1 h73754d4_0
+ license: GPL-2.0-only OR FTL
purls: []
- size: 1042798
- timestamp: 1765256792743
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_16.conda
- sha256: 44bfc6fe16236babb271e0c693fe7fd978f336542e23c9c30e700483796ed30b
- md5: cf9cd6739a3b694dcf551d898e112331
+ size: 173114
+ timestamp: 1757945422243
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/freetype-2.14.1-h8af1aa0_0.conda
+ sha256: 9f8de35e95ce301cecfe01bc9d539c7cc045146ffba55efe9733ff77ad1cfb21
+ md5: 0c8f36ebd3678eed1685f0fc93fc2175
depends:
- - _openmp_mutex >=4.5
- constrains:
- - libgomp 15.2.0 h8acb6b2_16
- - libgcc-ng ==15.2.0=*_16
- license: GPL-3.0-only WITH GCC-exception-3.1
- license_family: GPL
+ - libfreetype 2.14.1 h8af1aa0_0
+ - libfreetype6 2.14.1 hdae7a39_0
+ license: GPL-2.0-only OR FTL
purls: []
- size: 620637
- timestamp: 1765256938043
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda
- sha256: 5b3e5e4e9270ecfcd48f47e3a68f037f5ab0f529ccb223e8e5d5ac75a58fc687
- md5: 26c46f90d0e727e95c6c9498a33a09f3
+ size: 173174
+ timestamp: 1757945489158
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/freetype-2.14.1-hce30654_0.conda
+ sha256: 14427aecd72e973a73d5f9dfd0e40b6bc3791d253de09b7bf233f6a9a190fd17
+ md5: 1ec9a1ee7a2c9339774ad9bb6fe6caec
depends:
- - __glibc >=2.17,<3.0.a0
- license: GPL-3.0-only WITH GCC-exception-3.1
- license_family: GPL
- purls: []
- size: 603284
- timestamp: 1765256703881
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_16.conda
- sha256: 0a9d77c920db691eb42b78c734d70c5a1d00b3110c0867cfff18e9dd69bc3c29
- md5: 4d2f224e8186e7881d53e3aead912f6c
- license: GPL-3.0-only WITH GCC-exception-3.1
- license_family: GPL
+ - libfreetype 2.14.1 hce30654_0
+ - libfreetype6 2.14.1 h6da58f4_0
+ license: GPL-2.0-only OR FTL
purls: []
- size: 587924
- timestamp: 1765256821307
-- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda
- sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8
- md5: 1a580f7796c7bf6393fddb8bbbde58dc
+ size: 173399
+ timestamp: 1757947175403
+- conda: https://conda.anaconda.org/conda-forge/noarch/gast-0.7.0-pyhd8ed1ab_0.conda
+ sha256: 587a0e2606026716760af58e5d7c15ea02a848bd076a324946798be29d0229db
+ md5: 377a825d91b5d6fcc0e6cdb98bbe9799
depends:
- - __glibc >=2.17,<3.0.a0
- - libgcc >=13
+ - python >=3.10
constrains:
- - xz 5.8.1.*
- license: 0BSD
- purls: []
- size: 112894
- timestamp: 1749230047870
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.1-h86ecc28_2.conda
- sha256: 498ea4b29155df69d7f20990a7028d75d91dbea24d04b2eb8a3d6ef328806849
- md5: 7d362346a479256857ab338588190da0
+ - pythran >=0.12.2
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/gast?source=hash-mapping
+ size: 27047
+ timestamp: 1764507196904
+- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda
+ sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff
+ md5: 3bf7b9fd5a7136126e0234db4b87c8b6
depends:
- - libgcc >=13
- constrains:
- - xz 5.8.1.*
- license: 0BSD
+ - libgcc-ng >=12
+ license: MIT
+ license_family: MIT
purls: []
- size: 125103
- timestamp: 1749232230009
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda
- sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285
- md5: d6df911d4564d77c4374b02552cb17d1
+ size: 77248
+ timestamp: 1712692454246
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda
+ sha256: a79dc3bd54c4fb1f249942ee2d5b601a76ecf9614774a4cff9af49adfa458db2
+ md5: 2f809afaf0ba1ea4135dce158169efac
depends:
- - __osx >=11.0
- constrains:
- - xz 5.8.1.*
- license: 0BSD
+ - libgcc-ng >=12
+ license: MIT
+ license_family: MIT
purls: []
- size: 92286
- timestamp: 1749230283517
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda
- sha256: 3aa92d4074d4063f2a162cd8ecb45dccac93e543e565c01a787e16a43501f7ee
- md5: c7e925f37e3b40d893459e625f6a53f1
+ size: 82124
+ timestamp: 1712692444545
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/giflib-5.2.2-h93a5062_0.conda
+ sha256: 843b3f364ff844137e37d5c0a181f11f6d51adcedd216f019d074e5aa5d7e09c
+ md5: 95fa1486c77505330c20f7202492b913
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 71613
+ timestamp: 1712692611426
+- conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda
+ sha256: 309cf4f04fec0c31b6771a5809a1909b4b3154a2208f52351e1ada006f4c750c
+ md5: c94a5994ef49749880a8139cf9afcbe1
depends:
- - __glibc >=2.17,<3.0.a0
- - libgcc >=13
- license: BSD-2-Clause
- license_family: BSD
+ - libgcc-ng >=12
+ - libstdcxx-ng >=12
+ license: GPL-2.0-or-later OR LGPL-3.0-or-later
purls: []
- size: 91183
- timestamp: 1748393666725
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-h86ecc28_0.conda
- sha256: ef8697f934c80b347bf9d7ed45650928079e303bad01bd064995b0e3166d6e7a
- md5: 78cfed3f76d6f3f279736789d319af76
+ size: 460055
+ timestamp: 1718980856608
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmp-6.3.0-h0a1ffab_2.conda
+ sha256: a5e341cbf797c65d2477b27d99091393edbaa5178c7d69b7463bb105b0488e69
+ md5: 7cbfb3a8bb1b78a7f5518654ac6725ad
depends:
- - libgcc >=13
- license: BSD-2-Clause
- license_family: BSD
+ - libgcc-ng >=12
+ - libstdcxx-ng >=12
+ license: GPL-2.0-or-later OR LGPL-3.0-or-later
purls: []
- size: 114064
- timestamp: 1748393729243
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda
- sha256: 0a1875fc1642324ebd6c4ac864604f3f18f57fbcf558a8264f6ced028a3c75b2
- md5: 85ccccb47823dd9f7a99d2c7f530342f
+ size: 417323
+ timestamp: 1718980707330
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gmp-6.3.0-h7bae524_2.conda
+ sha256: 76e222e072d61c840f64a44e0580c2503562b009090f55aa45053bf1ccb385dd
+ md5: eed7278dfbab727b56f2c0b64330814b
depends:
- __osx >=11.0
- license: BSD-2-Clause
- license_family: BSD
+ - libcxx >=16
+ license: GPL-2.0-or-later OR LGPL-3.0-or-later
purls: []
- size: 71829
- timestamp: 1748393749336
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_0.conda
- sha256: 6f0e8a812e8e33a4d8b7a0e595efe28373080d27b78ee4828aa4f6649a088454
- md5: 2e1b84d273b01835256e53fd938de355
+ size: 365188
+ timestamp: 1718981343258
+- conda: https://conda.anaconda.org/conda-forge/linux-64/gmpy2-2.2.1-py312hcaba1f9_2.conda
+ sha256: c9dfe9be6716d992b4ddd2e8219ad8afbe33dc04f69748ac4302954ba2e29e84
+ md5: dd6f5de6249439ab97a6e9e873741294
depends:
- __glibc >=2.17,<3.0.a0
+ - gmp >=6.3.0,<7.0a0
- libgcc >=14
- - libzlib >=1.3.1,<2.0a0
- license: blessing
- purls: []
- size: 938979
- timestamp: 1764359444435
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.51.1-h022381a_0.conda
- sha256: e394dd772b71dbcd653d078f3aacf6e26e3478bd6736a687ab86e463a2f153a8
- md5: 233efdd411317d2dc5fde72464b3df7a
+ - mpc >=1.3.1,<2.0a0
+ - mpfr >=4.2.1,<5.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: LGPL-3.0-or-later
+ license_family: LGPL
+ purls:
+ - pkg:pypi/gmpy2?source=hash-mapping
+ size: 214554
+ timestamp: 1762946924209
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gmpy2-2.2.1-py312h35d709e_2.conda
+ sha256: ce6de9f7af4940bfd41007c179aad3c4c5db72cccaf6bc6ed0916cefb59c41b2
+ md5: f7c553f4856e53e057f09a0076281c00
depends:
+ - gmp >=6.3.0,<7.0a0
- libgcc >=14
- - libzlib >=1.3.1,<2.0a0
- license: blessing
- purls: []
- size: 939207
- timestamp: 1764359457549
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h9a5124b_0.conda
- sha256: a46b167447e2a9e38586320c30b29e3b68b6f7e6b873c18d6b1aa2efd2626917
- md5: 67e50e5bd4e5e2310d66b88c4da50096
+ - mpc >=1.3.1,<2.0a0
+ - mpfr >=4.2.1,<5.0a0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: LGPL-3.0-or-later
+ license_family: LGPL
+ purls:
+ - pkg:pypi/gmpy2?source=hash-mapping
+ size: 204926
+ timestamp: 1762946936234
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gmpy2-2.2.1-py312hee6aa52_2.conda
+ sha256: e2f72ddb929fcd161d68729891f25241d62ab1a9d4e37d0284f2b2fce88935fa
+ md5: bed6eebc8d1690f205a781c993f9bc65
depends:
- __osx >=11.0
- - libzlib >=1.3.1,<2.0a0
- license: blessing
- purls: []
- size: 906292
- timestamp: 1764359907797
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-h5347b49_1.conda
- sha256: 030447cf827c471abd37092ab9714fde82b8222106f22fde94bc7a64e2704c40
- md5: 41f5c09a211985c3ce642d60721e7c3e
+ - gmp >=6.3.0,<7.0a0
+ - mpc >=1.3.1,<2.0a0
+ - mpfr >=4.2.1,<5.0a0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: LGPL-3.0-or-later
+ license_family: LGPL
+ purls:
+ - pkg:pypi/gmpy2?source=hash-mapping
+ size: 161203
+ timestamp: 1762947199346
+- conda: https://conda.anaconda.org/conda-forge/noarch/google-pasta-0.2.0-pyhd8ed1ab_2.conda
+ sha256: 9f668fe562a9cf71a5d1f348645ac041af3f2e4bc634b18d6374e838e1c55dd8
+ md5: 005b9749218cb8c9e94ac2a77ca3c8c0
+ depends:
+ - python >=3.9
+ - six
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/google-pasta?source=hash-mapping
+ size: 49210
+ timestamp: 1733852592869
+- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda
+ sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c
+ md5: 2cd94587f3a401ae05e03a6caf09539d
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=14
- license: BSD-3-Clause
- license_family: BSD
+ - libstdcxx >=14
+ license: LGPL-2.0-or-later
+ license_family: LGPL
purls: []
- size: 40235
- timestamp: 1764790744114
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.2-h1022ec0_1.conda
- sha256: 3113c857e36779d94cf9a18236a710ceca0e94230b3bfeba0d134f33ee8c9ecd
- md5: 15b2cc72b9b05bcb141810b1bada654f
+ size: 99596
+ timestamp: 1755102025473
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda
+ sha256: c9b1781fe329e0b77c5addd741e58600f50bef39321cae75eba72f2f381374b7
+ md5: 4aa540e9541cc9d6581ab23ff2043f13
depends:
- libgcc >=14
+ - libstdcxx >=14
+ license: LGPL-2.0-or-later
+ license_family: LGPL
+ purls: []
+ size: 102400
+ timestamp: 1755102000043
+- conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.3.0-py312h1289d80_0.conda
+ sha256: 40522a733920e03853f7c625b2251ee9f2c62358de9785f2e7dbc69ee5f08744
+ md5: 83ce8529c70d9f5a6aef1cd0819e1238
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/greenlet?source=hash-mapping
+ size: 239282
+ timestamp: 1764863742698
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/greenlet-3.3.0-py312h1ab2c47_0.conda
+ sha256: b2f5edd8d38bed25889222335ab24f42ccb9e696992b191ac3d88156b597de74
+ md5: 3b6893dafd2a978664ec6f20eee8949e
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/greenlet?source=hash-mapping
+ size: 240955
+ timestamp: 1764863771365
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/greenlet-3.3.0-py312h455b684_0.conda
+ sha256: f2810adaa7a12902c53e8c46598be97074178edcb2e4c15de89a2fa182f62319
+ md5: 05c6af3d27e8e073787c281b7761422d
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/greenlet?source=hash-mapping
+ size: 233656
+ timestamp: 1764863941582
+- conda: https://conda.anaconda.org/conda-forge/linux-64/grpcio-1.73.1-py312h6f3464c_1.conda
+ sha256: 9b6ef222599d63ca23a9e292c35f454756e321cce52af9f5142303230f0c2762
+ md5: dca50c100d8d67882ada32756810372f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libgrpc 1.73.1 h3288cfb_1
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/grpcio?source=hash-mapping
+ size: 885879
+ timestamp: 1761058885541
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/grpcio-1.67.1-py312h37c5e5d_2.conda
+ sha256: 84fbead73c4f01e35aec419383be2998f8fc3cea33c298be7d5184199366117d
+ md5: 003b0e09b86cb9ae16f28f57c46fac36
+ depends:
+ - libgcc >=13
+ - libgrpc 1.67.1 hf7ccdd3_2
+ - libstdcxx >=13
+ - libzlib >=1.3.1,<2.0a0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/grpcio?source=hash-mapping
+ size: 871386
+ timestamp: 1740786872746
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/grpcio-1.67.1-py312he4e58e5_2.conda
+ sha256: f7ffc67cae79114a63f3da9ae1ff97e0719b82b8334d984f1bbc485d3673f960
+ md5: 905296f2713c79017fc9ea11bd57ecfe
+ depends:
+ - __osx >=11.0
+ - libcxx >=18
+ - libgrpc 1.67.1 h0a426d6_2
+ - libzlib >=1.3.1,<2.0a0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/grpcio?source=hash-mapping
+ size: 814879
+ timestamp: 1740786902083
+- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda
+ sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3
+ md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9
+ depends:
+ - python >=3.10
+ - hyperframe >=6.1,<7
+ - hpack >=4.1,<5
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/h2?source=hash-mapping
+ size: 95967
+ timestamp: 1756364871835
+- conda: https://conda.anaconda.org/conda-forge/linux-64/h5py-3.15.1-nompi_py312ha4f8f14_101.conda
+ sha256: bb5cefbe5b54195a54f749189fc6797568d52e8790b2f542143c681b98a92b71
+ md5: 23965cb240cb534649dfe2327ecec4fa
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - cached-property
+ - hdf5 >=1.14.6,<1.14.7.0a0
+ - libgcc >=14
+ - numpy >=1.23,<3
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/h5py?source=hash-mapping
+ size: 1290741
+ timestamp: 1764016665782
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/h5py-3.15.1-nompi_py312hb54937b_101.conda
+ sha256: 9a093ee0e3046ab9ccb305f3ea76209914b0ab5e1f66a7e4bc1f2a6169a0365a
+ md5: 3e8eb0d6ab1ac964a4e711009baf19fe
+ depends:
+ - cached-property
+ - hdf5 >=1.14.6,<1.14.7.0a0
+ - libgcc >=14
+ - numpy >=1.23,<3
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/h5py?source=hash-mapping
+ size: 1261492
+ timestamp: 1764016761746
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/h5py-3.15.1-nompi_py312h4eecd6b_101.conda
+ sha256: 914d4f00a4d8cb86a70ce60241acc631a0e9d0cd939c0091b06de2d6cef51a3b
+ md5: 1f19a033f9c3f388c8f3d3c1643d6611
+ depends:
+ - __osx >=11.0
+ - cached-property
+ - hdf5 >=1.14.6,<1.14.7.0a0
+ - numpy >=1.23,<3
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
license: BSD-3-Clause
license_family: BSD
+ purls:
+ - pkg:pypi/h5py?source=hash-mapping
+ size: 1139768
+ timestamp: 1764017732485
+- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-12.2.0-h15599e2_0.conda
+ sha256: 6bd8b22beb7d40562b2889dc68232c589ff0d11a5ad3addd41a8570d11f039d9
+ md5: b8690f53007e9b5ee2c2178dd4ac778c
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - cairo >=1.18.4,<2.0a0
+ - graphite2 >=1.3.14,<2.0a0
+ - icu >=75.1,<76.0a0
+ - libexpat >=2.7.1,<3.0a0
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - libgcc >=14
+ - libglib >=2.86.1,<3.0a0
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: MIT
+ license_family: MIT
purls: []
- size: 43415
- timestamp: 1764790752623
-- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
- sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4
- md5: edb0dca6bc32e4f4789199455a1dbeb8
+ size: 2411408
+ timestamp: 1762372726141
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-12.2.0-he4899c9_0.conda
+ sha256: 5cfd74a3fbce0921af5beff93a3fe7edc5b1344d9b9668b2de1c1be932b54993
+ md5: 1437bf9690976948f90175a65407b65f
+ depends:
+ - cairo >=1.18.4,<2.0a0
+ - graphite2 >=1.3.14,<2.0a0
+ - icu >=75.1,<76.0a0
+ - libexpat >=2.7.1,<3.0a0
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - libgcc >=14
+ - libglib >=2.86.1,<3.0a0
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 2156041
+ timestamp: 1762376447693
+- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h1b119a7_104.conda
+ sha256: 454e9724b322cee277abd7acf4f8d688e9c4ded006b6d5bc9fcc2a1ff907d27a
+ md5: 0857f4d157820dcd5625f61fdfefb780
depends:
- __glibc >=2.17,<3.0.a0
- - libgcc >=13
- constrains:
- - zlib 1.3.1 *_2
- license: Zlib
- license_family: Other
+ - libaec >=1.1.4,<2.0a0
+ - libcurl >=8.17.0,<9.0a0
+ - libgcc >=14
+ - libgfortran
+ - libgfortran5 >=14.3.0
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ license: BSD-3-Clause
+ license_family: BSD
purls: []
- size: 60963
- timestamp: 1727963148474
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda
- sha256: 5a2c1eeef69342e88a98d1d95bff1603727ab1ff4ee0e421522acd8813439b84
- md5: 08aad7cbe9f5a6b460d0976076b6ae64
+ size: 3720961
+ timestamp: 1764771748126
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/hdf5-1.14.6-nompi_hc619b4a_104.conda
+ sha256: ffb7d1f79e4e5c7ca267cb47e552aadad40a3fe70367af3ace56b2d7c2707740
+ md5: 8b090efce0a74026d56350bae0c5a23b
depends:
- - libgcc >=13
- constrains:
- - zlib 1.3.1 *_2
- license: Zlib
- license_family: Other
+ - libaec >=1.1.4,<2.0a0
+ - libcurl >=8.17.0,<9.0a0
+ - libgcc >=14
+ - libgfortran
+ - libgfortran5 >=14.3.0
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ license: BSD-3-Clause
+ license_family: BSD
purls: []
- size: 66657
- timestamp: 1727963199518
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
- sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b
- md5: 369964e85dc26bfe78f41399b366c435
+ size: 3910170
+ timestamp: 1764780020825
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/hdf5-1.14.6-nompi_hd3baa01_104.conda
+ sha256: 3cd591334a838b127dfe8a626f38241892063eac8873abb93255962c71155533
+ md5: 5a1cbaf2349dd2e6dd6cfaab378de51b
depends:
- __osx >=11.0
- constrains:
- - zlib 1.3.1 *_2
- license: Zlib
- license_family: Other
+ - libaec >=1.1.4,<2.0a0
+ - libcurl >=8.17.0,<9.0a0
+ - libcxx >=19
+ - libgfortran
+ - libgfortran5 >=14.3.0
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ license: BSD-3-Clause
+ license_family: BSD
purls: []
- size: 46438
- timestamp: 1727963202283
-- pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
- name: logistro
- version: 2.0.1
- sha256: 06ffa127b9fb4ac8b1972ae6b2a9d7fde57598bf5939cd708f43ec5bba2d31eb
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl
- name: mako
- version: 1.3.10
- sha256: baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59
- requires_dist:
- - markupsafe>=0.9.2
- - pytest ; extra == 'testing'
- - babel ; extra == 'babel'
- - lingua ; extra == 'lingua'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl
- name: markdown
- version: '3.10'
- sha256: b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c
- requires_dist:
- - coverage ; extra == 'testing'
- - pyyaml ; extra == 'testing'
- - mkdocs>=1.6 ; extra == 'docs'
- - mkdocs-nature>=0.6 ; extra == 'docs'
- - mdx-gh-links>=0.2 ; extra == 'docs'
- - mkdocstrings[python] ; extra == 'docs'
- - mkdocs-gen-files ; extra == 'docs'
- - mkdocs-section-index ; extra == 'docs'
- - mkdocs-literate-nav ; extra == 'docs'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl
- name: markdown-it-py
- version: 4.0.0
- sha256: 87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147
- requires_dist:
- - mdurl~=0.1
- - psutil ; extra == 'benchmarking'
- - pytest ; extra == 'benchmarking'
- - pytest-benchmark ; extra == 'benchmarking'
- - commonmark~=0.9 ; extra == 'compare'
- - markdown~=3.4 ; extra == 'compare'
- - mistletoe~=1.0 ; extra == 'compare'
- - mistune~=3.0 ; extra == 'compare'
- - panflute~=2.3 ; extra == 'compare'
- - markdown-it-pyrs ; extra == 'compare'
- - linkify-it-py>=1,<3 ; extra == 'linkify'
- - mdit-py-plugins>=0.5.0 ; extra == 'plugins'
- - gprof2dot ; extra == 'profiling'
- - mdit-py-plugins>=0.5.0 ; extra == 'rtd'
- - myst-parser ; extra == 'rtd'
- - pyyaml ; extra == 'rtd'
- - sphinx ; extra == 'rtd'
- - sphinx-copybutton ; extra == 'rtd'
- - sphinx-design ; extra == 'rtd'
- - sphinx-book-theme~=1.0 ; extra == 'rtd'
- - jupyter-sphinx ; extra == 'rtd'
- - ipykernel ; extra == 'rtd'
- - coverage ; extra == 'testing'
- - pytest ; extra == 'testing'
- - pytest-cov ; extra == 'testing'
- - pytest-regressions ; extra == 'testing'
- - requests ; extra == 'testing'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: markupsafe
- version: 3.0.3
- sha256: 133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl
- name: markupsafe
- version: 3.0.3
- sha256: 116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- name: markupsafe
- version: 3.0.3
- sha256: ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- name: matplotlib
- version: 3.10.8
- sha256: 646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce
- requires_dist:
- - contourpy>=1.0.1
- - cycler>=0.10
- - fonttools>=4.22.0
- - kiwisolver>=1.3.1
- - numpy>=1.23
- - packaging>=20.0
- - pillow>=8
- - pyparsing>=3
- - python-dateutil>=2.7
- - meson-python>=0.13.1,<0.17.0 ; extra == 'dev'
- - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev'
- - setuptools-scm>=7 ; extra == 'dev'
- - setuptools>=64 ; extra == 'dev'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- name: matplotlib
- version: 3.10.8
- sha256: a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486
- requires_dist:
- - contourpy>=1.0.1
- - cycler>=0.10
- - fonttools>=4.22.0
- - kiwisolver>=1.3.1
- - numpy>=1.23
- - packaging>=20.0
- - pillow>=8
- - pyparsing>=3
- - python-dateutil>=2.7
- - meson-python>=0.13.1,<0.17.0 ; extra == 'dev'
- - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev'
- - setuptools-scm>=7 ; extra == 'dev'
- - setuptools>=64 ; extra == 'dev'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl
- name: matplotlib
- version: 3.10.8
- sha256: 56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1
- requires_dist:
- - contourpy>=1.0.1
- - cycler>=0.10
- - fonttools>=4.22.0
- - kiwisolver>=1.3.1
- - numpy>=1.23
- - packaging>=20.0
- - pillow>=8
- - pyparsing>=3
- - python-dateutil>=2.7
- - meson-python>=0.13.1,<0.17.0 ; extra == 'dev'
- - pybind11>=2.13.2,!=2.13.3 ; extra == 'dev'
- - setuptools-scm>=7 ; extra == 'dev'
- - setuptools>=64 ; extra == 'dev'
- requires_python: '>=3.10'
-- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
- sha256: 9b0037171dad0100f0296699a11ae7d355237b55f42f9094aebc0f41512d96a1
- md5: 827064ddfe0de2917fb29f1da4f8f533
+ size: 3292042
+ timestamp: 1764771887501
+- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
+ sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba
+ md5: 0a802cb9888dd14eeefc611f05c40b6e
depends:
- python >=3.9
license: MIT
license_family: MIT
purls:
- - pkg:pypi/mccabe?source=hash-mapping
- size: 12934
- timestamp: 1733216573915
-- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl
- name: mdurl
- version: 0.1.2
- sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- name: ml-dtypes
- version: 0.5.4
- sha256: ce756d3a10d0c4067172804c9cc276ba9cc0ff47af9078ad439b075d1abdc29b
- requires_dist:
- - numpy>=1.21
- - numpy>=1.21.2 ; python_full_version >= '3.10'
- - numpy>=1.23.3 ; python_full_version >= '3.11'
- - numpy>=1.26.0 ; python_full_version >= '3.12'
- - numpy>=2.1.0 ; python_full_version >= '3.13'
- - absl-py ; extra == 'dev'
- - pytest ; extra == 'dev'
- - pytest-xdist ; extra == 'dev'
- - pylint>=2.6.0 ; extra == 'dev'
- - pyink ; extra == 'dev'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl
- name: ml-dtypes
- version: 0.5.4
- sha256: 8c760d85a2f82e2bed75867079188c9d18dae2ee77c25a54d60e9cc79be1bc48
- requires_dist:
- - numpy>=1.21
- - numpy>=1.21.2 ; python_full_version >= '3.10'
- - numpy>=1.23.3 ; python_full_version >= '3.11'
- - numpy>=1.26.0 ; python_full_version >= '3.12'
- - numpy>=2.1.0 ; python_full_version >= '3.13'
- - absl-py ; extra == 'dev'
- - pytest ; extra == 'dev'
- - pytest-xdist ; extra == 'dev'
- - pylint>=2.6.0 ; extra == 'dev'
- - pyink ; extra == 'dev'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: ml-dtypes
- version: 0.5.4
- sha256: 533ce891ba774eabf607172254f2e7260ba5f57bdd64030c9a4fcfbd99815d0d
- requires_dist:
- - numpy>=1.21
- - numpy>=1.21.2 ; python_full_version >= '3.10'
- - numpy>=1.23.3 ; python_full_version >= '3.11'
- - numpy>=1.26.0 ; python_full_version >= '3.12'
- - numpy>=2.1.0 ; python_full_version >= '3.13'
- - absl-py ; extra == 'dev'
- - pytest ; extra == 'dev'
- - pytest-xdist ; extra == 'dev'
- - pylint>=2.6.0 ; extra == 'dev'
- - pyink ; extra == 'dev'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- name: mpmath
- version: 1.3.0
- sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c
- requires_dist:
- - pytest>=4.6 ; extra == 'develop'
- - pycodestyle ; extra == 'develop'
- - pytest-cov ; extra == 'develop'
- - codecov ; extra == 'develop'
- - wheel ; extra == 'develop'
- - sphinx ; extra == 'docs'
- - gmpy2>=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy'
- - pytest>=4.6 ; extra == 'tests'
-- pypi: https://files.pythonhosted.org/packages/b2/bc/465daf1de06409cdd4532082806770ee0d8d7df434da79c76564d0f69741/namex-0.1.0-py3-none-any.whl
- name: namex
- version: 0.1.0
- sha256: e2012a474502f1e2251267062aae3114611f07df4224b6e06334c57b0f2ce87c
-- pypi: https://files.pythonhosted.org/packages/79/3e/b8ecc67e178919671695f64374a7ba916cf0adbf86efedc6054f38b5b8ae/narwhals-2.14.0-py3-none-any.whl
- name: narwhals
- version: 2.14.0
- sha256: b56796c9a00179bd757d15282c540024e1d5c910b19b8c9944d836566c030acf
- requires_dist:
- - cudf>=24.10.0 ; extra == 'cudf'
- - dask[dataframe]>=2024.8 ; extra == 'dask'
- - duckdb>=1.1 ; extra == 'duckdb'
- - ibis-framework>=6.0.0 ; extra == 'ibis'
- - packaging ; extra == 'ibis'
- - pyarrow-hotfix ; extra == 'ibis'
- - rich ; extra == 'ibis'
- - modin ; extra == 'modin'
- - pandas>=1.1.3 ; extra == 'pandas'
- - polars>=0.20.4 ; extra == 'polars'
- - pyarrow>=13.0.0 ; extra == 'pyarrow'
- - pyspark>=3.5.0 ; extra == 'pyspark'
- - pyspark[connect]>=3.5.0 ; extra == 'pyspark-connect'
- - sqlframe>=3.22.0,!=3.39.3 ; extra == 'sqlframe'
- requires_python: '>=3.9'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
- sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586
- md5: 47e340acb35de30501a76c7c799c41d7
+ - pkg:pypi/hpack?source=hash-mapping
+ size: 30731
+ timestamp: 1737618390337
+- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda
+ sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d
+ md5: 7fe569c10905402ed47024fc481bb371
+ depends:
+ - __unix
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/humanfriendly?source=hash-mapping
+ size: 73563
+ timestamp: 1733928021866
+- 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
+ size: 17397
+ timestamp: 1737618427549
+- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda
+ sha256: 71e750d509f5fa3421087ba88ef9a7b9be11c53174af3aa4d06aff4c18b38e8e
+ md5: 8b189310083baabfb622af68fd9d3ae3
depends:
- __glibc >=2.17,<3.0.a0
- - libgcc >=13
- license: X11 AND BSD-3-Clause
+ - libgcc-ng >=12
+ - libstdcxx-ng >=12
+ license: MIT
+ license_family: MIT
purls: []
- size: 891641
- timestamp: 1738195959188
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda
- sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468
- md5: 182afabe009dc78d8b73100255ee6868
+ size: 12129203
+ timestamp: 1720853576813
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-75.1-hf9b3779_0.conda
+ sha256: 813298f2e54ef087dbfc9cc2e56e08ded41de65cff34c639cc8ba4e27e4540c9
+ md5: 268203e8b983fddb6412b36f2024e75c
depends:
- - libgcc >=13
- license: X11 AND BSD-3-Clause
+ - libgcc-ng >=12
+ - libstdcxx-ng >=12
+ license: MIT
+ license_family: MIT
purls: []
- size: 926034
- timestamp: 1738196018799
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
- sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733
- md5: 068d497125e4bf8a66bf707254fff5ae
+ size: 12282786
+ timestamp: 1720853454991
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda
+ sha256: 9ba12c93406f3df5ab0a43db8a4b4ef67a5871dfd401010fbe29b218b2cbe620
+ md5: 5eb22c1d7b3fc4abb50d92d621583137
depends:
- __osx >=11.0
- license: X11 AND BSD-3-Clause
+ license: MIT
+ license_family: MIT
purls: []
- size: 797030
- timestamp: 1738196177597
-- pypi: https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- name: numpy
- version: 2.4.0
- sha256: f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: numpy
- version: 2.4.0
- sha256: 8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl
- name: numpy
- version: 2.4.0
- sha256: 39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/4a/4e/44dbb46b3d1b0ec61afda8e84837870f2f9ace33c564317d59b70bc19d3e/nvidia_nccl_cu12-2.28.9-py3-none-manylinux_2_18_x86_64.whl
- name: nvidia-nccl-cu12
- version: 2.28.9
- sha256: 485776daa8447da5da39681af455aa3b2c2586ddcf4af8772495e7c532c7e5ab
- requires_python: '>=3'
-- pypi: https://files.pythonhosted.org/packages/5e/19/2caa972a31014a8cb4525f715f2a75d93caef9d4b9da2809cc05d0489e43/onnx-1.20.0-cp312-abi3-macosx_12_0_universal2.whl
- name: onnx
- version: 1.20.0
- sha256: 31efe37d7d1d659091f34ddd6a31780334acf7c624176832db9a0a8ececa8fb5
- requires_dist:
- - numpy>=1.23.2
- - protobuf>=4.25.1
- - typing-extensions>=4.7.1
- - ml-dtypes>=0.5.0
- - pillow ; extra == 'reference'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/78/bb/b98732309f2f6beb4cdcf7b955d7bbfd75a191185370ee21233373db381e/onnx-1.20.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- name: onnx
- version: 1.20.0
- sha256: d75da05e743eb9a11ff155a775cae5745e71f1cd0ca26402881b8f20e8d6e449
- requires_dist:
- - numpy>=1.23.2
- - protobuf>=4.25.1
- - typing-extensions>=4.7.1
- - ml-dtypes>=0.5.0
- - pillow ; extra == 'reference'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/84/a7/38aa564871d062c11538d65c575af9c7e057be880c09ecbd899dd1abfa83/onnx-1.20.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: onnx
- version: 1.20.0
- sha256: 02e0d72ab09a983fce46686b155a5049898558d9f3bc6e8515120d6c40666318
- requires_dist:
- - numpy>=1.23.2
- - protobuf>=4.25.1
- - typing-extensions>=4.7.1
- - ml-dtypes>=0.5.0
- - pillow ; extra == 'reference'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/4a/67/8dca1868a6e226f8d3f7d666cb6a48b79a60aad5267b16b24627cd8d9eb8/onnxconverter_common-1.16.0-py2.py3-none-any.whl
- name: onnxconverter-common
- version: 1.16.0
- sha256: df39ee96f17fff119dff10dd245467651b60b9e8a96020eb93402239794852f7
+ size: 11857802
+ timestamp: 1720853997952
+- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda
+ sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0
+ md5: 53abe63df7e10a6ba605dc5f9f961d36
+ depends:
+ - python >=3.10
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/idna?source=hash-mapping
+ size: 50721
+ timestamp: 1760286526795
+- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda
+ sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745
+ md5: 63ccfdc3a3ce25b027b8767eb722fca8
+ depends:
+ - python >=3.9
+ - zipp >=3.20
+ - python
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/importlib-metadata?source=hash-mapping
+ size: 34641
+ timestamp: 1747934053147
+- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
+ sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19
+ md5: 9614359868482abba1bd15ce465e3c42
+ depends:
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/iniconfig?source=compressed-mapping
+ size: 13387
+ timestamp: 1760831448842
+- conda: https://conda.anaconda.org/conda-forge/noarch/isort-7.0.0-pyhd8ed1ab_0.conda
+ sha256: 13b0005877f553eb2e5c50447c9d0047e7257124ec2d1569d7dad35697790237
+ md5: 55a61979242077b2cc377c74326ea9f0
+ depends:
+ - importlib-metadata >=4.6.0
+ - python >=3.10,<4.0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/isort?source=hash-mapping
+ size: 74876
+ timestamp: 1760192714356
+- conda: https://conda.anaconda.org/conda-forge/noarch/joblib-1.5.3-pyhd8ed1ab_0.conda
+ sha256: 301539229d7be6420c084490b8145583291123f0ce6b92f56be5948a2c83a379
+ md5: 615de2a4d97af50c350e5cf160149e77
+ depends:
+ - python >=3.10
+ - setuptools
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/joblib?source=hash-mapping
+ size: 226448
+ timestamp: 1765794135253
+- pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl
+ name: kaleido
+ version: 1.2.0
+ sha256: c27ed82b51df6b923d0e656feac221343a0dbcd2fb9bc7e6b1db97f61e9a1513
requires_dist:
- - numpy
- - onnx
+ - choreographer>=1.1.1
+ - logistro>=1.0.8
+ - orjson>=3.10.15
- packaging
- - protobuf>=3.20.2
- - pytest ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - ruff ; extra == 'lint'
- - pyright ; extra == 'lint'
- - onnxconverter-common[lint,test] ; extra == 'dev'
+ - pytest-timeout>=2.4.0
requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/29/09/c5b247a11ece1cbf8650bdba12d556fb2ef5a5a7e6675fa8edeea889c38e/onnxmltools-1.14.0-py2.py3-none-any.whl
- name: onnxmltools
- version: 1.14.0
- sha256: 8036cdcc16d50cf91fe7470d4a91a5bd7d2006170d052b051f33287aa7615252
- requires_dist:
+- conda: https://conda.anaconda.org/conda-forge/noarch/keras-3.12.0-pyh753f3f9_0.conda
+ sha256: fc14954b4f916bade17fa03fc57371f1578236c3e4d5934926fef32880c87844
+ md5: 3e82727e0621a5d90ea57e4e345f42be
+ depends:
+ - absl-py
+ - h5py
+ - ml_dtypes
+ - namex
- numpy
- - onnx
-- pypi: https://files.pythonhosted.org/packages/1c/a1/428ee29c6eaf09a6f6be56f836213f104618fb35ac6cc586ff0f477263eb/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- name: onnxruntime
- version: 1.23.2
- sha256: 45d127d6e1e9b99d1ebeae9bcd8f98617a812f53f46699eafeb976275744826b
- requires_dist:
- - coloredlogs
- - flatbuffers
- - numpy>=1.21.6
+ - optree
- packaging
- - protobuf
- - sympy
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/3d/41/fba0cabccecefe4a1b5fc8020c44febb334637f133acefc7ec492029dd2c/onnxruntime-1.23.2-cp313-cp313-macosx_13_0_arm64.whl
- name: onnxruntime
- version: 1.23.2
- sha256: 2ff531ad8496281b4297f32b83b01cdd719617e2351ffe0dba5684fb283afa1f
- requires_dist:
- - coloredlogs
- - flatbuffers
- - numpy>=1.21.6
- - packaging
- - protobuf
- - sympy
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/f2/2b/b57c8a2466a3126dbe0a792f56ad7290949b02f47b86216cd47d857e4b77/onnxruntime-1.23.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: onnxruntime
- version: 1.23.2
- sha256: 8bace4e0d46480fbeeb7bbe1ffe1f080e6663a42d1086ff95c1551f2d39e7872
- requires_dist:
- - coloredlogs
- - flatbuffers
- - numpy>=1.21.6
- - packaging
- - protobuf
- - sympy
- requires_python: '>=3.10'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
- sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d
- md5: 9ee58d5c534af06558933af3c845a780
+ - python >=3.10
+ - rich
+ constrains:
+ - tensorflow >=2.18.0
+ - pytorch >=2.6.0
+ - jax >=0.5.0
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/keras?source=hash-mapping
+ size: 841185
+ timestamp: 1761616624583
+- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda
+ sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4
+ md5: b38117a3c920364aff79f870c984b4a3
depends:
- __glibc >=2.17,<3.0.a0
- - ca-certificates
- - libgcc >=14
- license: Apache-2.0
- license_family: Apache
+ - libgcc >=13
+ license: LGPL-2.1-or-later
purls: []
- size: 3165399
- timestamp: 1762839186699
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.0-h8e36d6e_0.conda
- sha256: 8dd3b4c31fe176a3e51c5729b2c7f4c836a2ce3bd5c82082dc2a503ba9ee0af3
- md5: 7624c6e01aecba942e9115e0f5a2af9d
+ size: 134088
+ timestamp: 1754905959823
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda
+ sha256: 5ce830ca274b67de11a7075430a72020c1fb7d486161a82839be15c2b84e9988
+ md5: e7df0aab10b9cbb73ab2a467ebfaf8c7
depends:
- - ca-certificates
- - libgcc >=14
- license: Apache-2.0
- license_family: Apache
+ - libgcc >=13
+ license: LGPL-2.1-or-later
purls: []
- size: 3705625
- timestamp: 1762841024958
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
- sha256: ebe93dafcc09e099782fe3907485d4e1671296bc14f8c383cb6f3dfebb773988
- md5: b34dc4172653c13dcf453862f251af2b
+ size: 129048
+ timestamp: 1754906002667
+- conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.9-py312h0a2e395_2.conda
+ sha256: 170d76b7ac7197012bb048e1021482a7b2455f3592a5e8d97c96f285ebad064b
+ md5: 3a3004fddd39e3bb1a631b08d7045156
depends:
- - __osx >=11.0
- - ca-certificates
- license: Apache-2.0
- license_family: Apache
- purls: []
- size: 3108371
- timestamp: 1762839712322
-- pypi: https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl
- name: opt-einsum
- version: 3.4.0
- sha256: 69bb92469f86a1565195ece4ac0323943e83477171b91d24c35afe028a90d7cd
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/09/67/51acf67b1b9850e990a1a9b3fa0afcb5bbe9d645b0b6b8be5b3f2dca8f04/optree-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
- name: optree
- version: 0.18.0
- sha256: fa8e3878a1857761d64f08a23b32140d29754a53f85f7c87186ced2b5b1b49cb
- requires_dist:
- - typing-extensions>=4.6.0
- - typing-extensions>=4.12.0 ; python_full_version >= '3.13'
- - jax ; extra == 'jax'
- - numpy ; extra == 'numpy'
- - torch ; extra == 'torch'
- - ruff ; extra == 'lint'
- - pylint[spelling] ; extra == 'lint'
- - mypy ; extra == 'lint'
- - doc8 ; extra == 'lint'
- - pyenchant ; extra == 'lint'
- - xdoctest ; extra == 'lint'
- - cpplint ; extra == 'lint'
- - pre-commit ; extra == 'lint'
- - pytest ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - covdefaults ; extra == 'test'
- - rich ; extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'linux' and extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'darwin' and extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'win32' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'linux' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'darwin' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'win32' and extra == 'test'
- - sphinx ; extra == 'docs'
- - sphinx-autoapi ; extra == 'docs'
- - sphinx-autobuild ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - sphinx-rtd-theme ; extra == 'docs'
- - sphinxcontrib-bibtex ; extra == 'docs'
- - sphinx-autodoc-typehints ; extra == 'docs'
- - docutils ; extra == 'docs'
- - jax[cpu] ; extra == 'docs'
- - numpy ; extra == 'docs'
- - torch ; extra == 'docs'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/19/68/0a761a4f1b2e56ffbf3f223e967074c1331404f6dfb2b2cda6ecf62f4653/optree-0.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: optree
- version: 0.18.0
- sha256: 328857d7a35129904b21164f6b0c2ff1d728ad1f5838589c5f437a16c94213c8
- requires_dist:
- - typing-extensions>=4.6.0
- - typing-extensions>=4.12.0 ; python_full_version >= '3.13'
- - jax ; extra == 'jax'
- - numpy ; extra == 'numpy'
- - torch ; extra == 'torch'
- - ruff ; extra == 'lint'
- - pylint[spelling] ; extra == 'lint'
- - mypy ; extra == 'lint'
- - doc8 ; extra == 'lint'
- - pyenchant ; extra == 'lint'
- - xdoctest ; extra == 'lint'
- - cpplint ; extra == 'lint'
- - pre-commit ; extra == 'lint'
- - pytest ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - covdefaults ; extra == 'test'
- - rich ; extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'linux' and extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'darwin' and extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'win32' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'linux' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'darwin' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'win32' and extra == 'test'
- - sphinx ; extra == 'docs'
- - sphinx-autoapi ; extra == 'docs'
- - sphinx-autobuild ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - sphinx-rtd-theme ; extra == 'docs'
- - sphinxcontrib-bibtex ; extra == 'docs'
- - sphinx-autodoc-typehints ; extra == 'docs'
- - docutils ; extra == 'docs'
- - jax[cpu] ; extra == 'docs'
- - numpy ; extra == 'docs'
- - torch ; extra == 'docs'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/24/22/ae957579e22d53d4d24de6bad0a3b3811612fd70a8ecd0c85c81253f22e3/optree-0.18.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
- name: optree
- version: 0.18.0
- sha256: 27611c6c122745a003b5be7aedba49ef86e9fef46d743c234596de0bde6dc679
- requires_dist:
- - typing-extensions>=4.6.0
- - typing-extensions>=4.12.0 ; python_full_version >= '3.13'
- - jax ; extra == 'jax'
- - numpy ; extra == 'numpy'
- - torch ; extra == 'torch'
- - ruff ; extra == 'lint'
- - pylint[spelling] ; extra == 'lint'
- - mypy ; extra == 'lint'
- - doc8 ; extra == 'lint'
- - pyenchant ; extra == 'lint'
- - xdoctest ; extra == 'lint'
- - cpplint ; extra == 'lint'
- - pre-commit ; extra == 'lint'
- - pytest ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - covdefaults ; extra == 'test'
- - rich ; extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'linux' and extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'darwin' and extra == 'test'
- - typing-extensions==4.6.0 ; python_full_version < '3.13' and sys_platform == 'win32' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'linux' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'darwin' and extra == 'test'
- - typing-extensions==4.12.0 ; python_full_version >= '3.13' and sys_platform == 'win32' and extra == 'test'
- - sphinx ; extra == 'docs'
- - sphinx-autoapi ; extra == 'docs'
- - sphinx-autobuild ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - sphinx-rtd-theme ; extra == 'docs'
- - sphinxcontrib-bibtex ; extra == 'docs'
- - sphinx-autodoc-typehints ; extra == 'docs'
- - docutils ; extra == 'docs'
- - jax[cpu] ; extra == 'docs'
- - numpy ; extra == 'docs'
- - torch ; extra == 'docs'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/58/de/3d8455b08cb6312f8cc46aacdf16c71d4d881a1db4a4140fc5ef31108422/optuna-4.6.0-py3-none-any.whl
- name: optuna
- version: 4.6.0
- sha256: 4c3a9facdef2b2dd7e3e2a8ae3697effa70fae4056fcf3425cfc6f5a40feb069
- requires_dist:
- - alembic>=1.5.0
- - colorlog
- - numpy
- - packaging>=20.0
- - sqlalchemy>=1.4.2
- - tqdm
- - pyyaml
- - asv>=0.5.0 ; extra == 'benchmark'
- - cma ; extra == 'benchmark'
- - virtualenv ; extra == 'benchmark'
- - black<25.9.0 ; extra == 'checking'
- - blackdoc<0.4.2 ; extra == 'checking'
- - flake8 ; extra == 'checking'
- - isort ; extra == 'checking'
- - mypy ; extra == 'checking'
- - mypy-boto3-s3 ; extra == 'checking'
- - scipy-stubs ; python_full_version >= '3.10' and extra == 'checking'
- - types-pyyaml ; extra == 'checking'
- - types-redis ; extra == 'checking'
- - types-setuptools ; extra == 'checking'
- - types-tqdm ; extra == 'checking'
- - typing-extensions>=3.10.0.0 ; extra == 'checking'
- - ase ; extra == 'document'
- - cmaes>=0.12.0 ; extra == 'document'
- - fvcore ; extra == 'document'
- - kaleido<0.4 ; extra == 'document'
- - lightgbm ; extra == 'document'
- - matplotlib!=3.6.0 ; extra == 'document'
- - pandas ; extra == 'document'
- - pillow ; extra == 'document'
- - plotly>=4.9.0 ; extra == 'document'
- - scikit-learn ; extra == 'document'
- - sphinx ; extra == 'document'
- - sphinx-copybutton ; extra == 'document'
- - sphinx-gallery ; extra == 'document'
- - sphinx-notfound-page ; extra == 'document'
- - sphinx-rtd-theme>=1.2.0 ; extra == 'document'
- - torch ; extra == 'document'
- - torchvision ; extra == 'document'
- - boto3 ; extra == 'optional'
- - cmaes>=0.12.0 ; extra == 'optional'
- - google-cloud-storage ; extra == 'optional'
- - matplotlib!=3.6.0 ; extra == 'optional'
- - pandas ; extra == 'optional'
- - plotly>=4.9.0 ; extra == 'optional'
- - redis ; extra == 'optional'
- - scikit-learn>=0.24.2 ; extra == 'optional'
- - scipy ; extra == 'optional'
- - torch ; extra == 'optional'
- - greenlet ; extra == 'optional'
- - grpcio ; extra == 'optional'
- - protobuf>=5.28.1 ; extra == 'optional'
- - coverage ; extra == 'test'
- - fakeredis[lua] ; extra == 'test'
- - kaleido<0.4 ; extra == 'test'
- - moto ; extra == 'test'
- - pytest ; extra == 'test'
- - pytest-xdist ; extra == 'test'
- - scipy>=1.9.2 ; extra == 'test'
- - torch ; extra == 'test'
- - greenlet ; extra == 'test'
- - grpcio ; extra == 'test'
- - protobuf>=5.28.1 ; extra == 'test'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
- name: optuna-integration
- version: 4.6.0
- sha256: a02ef2018c02d521d23e364110579c03e53a518894d9b9a76b246b5fb2e027fd
- requires_dist:
- - optuna
- - pytest ; extra == 'test'
- - coverage ; extra == 'test'
- - fakeredis[lua] ; extra == 'test'
- - grpcio ; extra == 'test'
- - protobuf>=5.28.1 ; extra == 'test'
- - black<25.9.0 ; extra == 'checking'
- - blackdoc<0.4.2 ; extra == 'checking'
- - hacking ; extra == 'checking'
- - isort ; extra == 'checking'
- - mypy ; extra == 'checking'
- - types-pyyaml ; extra == 'checking'
- - types-redis ; extra == 'checking'
- - types-setuptools ; extra == 'checking'
- - typing-extensions>=3.10.0.0 ; extra == 'checking'
- - mlflow ; extra == 'document'
- - pandas ; extra == 'document'
- - scikit-learn>=0.24.2 ; extra == 'document'
- - scipy>=1.9.2 ; python_full_version >= '3.9' and extra == 'document'
- - sphinx ; extra == 'document'
- - sphinx-notfound-page ; extra == 'document'
- - sphinx-rtd-theme ; extra == 'document'
- - allennlp ; extra == 'allennlp'
- - jsonnet ; extra == 'allennlp'
- - numpy<2.0.0 ; extra == 'allennlp'
- - psutil ; extra == 'allennlp'
- - chainer ; extra == 'chainer'
- - numpy<2.0.0 ; extra == 'chainer'
- - chainermn ; extra == 'chainermn'
- - numpy<2.0.0 ; extra == 'chainermn'
- - botorch<0.10.0 ; extra == 'botorch'
- - numpy<2.0.0 ; extra == 'catboost'
- - catboost ; extra == 'catboost'
- - numpy<2.0.0 ; extra == 'cma'
- - cma ; extra == 'cma'
- - comet-ml>=3.39.3 ; extra == 'comet'
- - distributed ; extra == 'dask'
- - fastai>=2.0.0 ; extra == 'fastai'
- - fastai>=2.0.0 ; extra == 'fastaiv2'
- - tensorflow ; extra == 'keras'
- - lightgbm ; extra == 'lightgbm'
- - scikit-learn ; extra == 'lightgbm'
- - mlflow ; extra == 'mlflow'
- - mxnet ; extra == 'mxnet'
- - gpytorch ; extra == 'pytorch-distributed'
- - gpytorch ; extra == 'pytorch-distributed'
- - pytorch-ignite ; extra == 'pytorch-ignite'
- - pytorch-ignite ; extra == 'pytorch-ignite'
- - lightning ; extra == 'pytorch-lightning'
- - lightning ; extra == 'pytorch-lightning'
- - numpy<2.0.0 ; extra == 'shap'
- - shap ; extra == 'shap'
- - pandas ; extra == 'sklearn'
- - scikit-learn ; extra == 'sklearn'
- - scipy ; extra == 'sklearn'
- - skorch ; extra == 'skorch'
- - tensorboard ; extra == 'tensorboard'
- - tensorflow ; extra == 'tensorboard'
- - tensorflow<=2.15.0 ; extra == 'tensorflow'
- - tensorflow ; extra == 'tfkeras'
- - wandb ; extra == 'wandb'
- - xgboost ; extra == 'xgboost'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl
- name: orjson
- version: 3.11.5
- sha256: 3b01799262081a4c47c035dd77c1301d40f568f77cc7ec1bb7db5d63b0a01629
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- name: orjson
- version: 3.11.5
- sha256: 894aea2e63d4f24a7f04a1908307c738d0dce992e9249e744b8f4e8dd9197f39
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- name: orjson
- version: 3.11.5
- sha256: 75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f
- requires_python: '>=3.9'
-- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
- sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991
- md5: 58335b26c38bf4a20f399384c33cbcf9
+ - python
+ - __glibc >=2.17,<3.0.a0
+ - libstdcxx >=14
+ - libgcc >=14
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/kiwisolver?source=hash-mapping
+ size: 77682
+ timestamp: 1762488738724
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kiwisolver-1.4.9-py312h1683e8e_2.conda
+ sha256: 04187c7cf56abd3cebd504e717724b817fc0952b08f0099e1523542da1aa90b0
+ md5: b1d3e3106c1d103d367298dcfa77837a
depends:
- - python >=3.8
- python
- license: Apache-2.0
- license_family: APACHE
+ - libstdcxx >=14
+ - libgcc >=14
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
purls:
- - pkg:pypi/packaging?source=hash-mapping
- size: 62477
- timestamp: 1745345660407
-- pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
- name: pandas
- version: 2.3.3
- sha256: 318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac
- requires_dist:
- - numpy>=1.22.4 ; python_full_version < '3.11'
- - numpy>=1.23.2 ; python_full_version == '3.11.*'
- - numpy>=1.26.0 ; python_full_version >= '3.12'
- - python-dateutil>=2.8.2
- - pytz>=2020.1
- - tzdata>=2022.7
- - hypothesis>=6.46.1 ; extra == 'test'
- - pytest>=7.3.2 ; extra == 'test'
- - pytest-xdist>=2.2.0 ; extra == 'test'
- - pyarrow>=10.0.1 ; extra == 'pyarrow'
- - bottleneck>=1.3.6 ; extra == 'performance'
- - numba>=0.56.4 ; extra == 'performance'
- - numexpr>=2.8.4 ; extra == 'performance'
- - scipy>=1.10.0 ; extra == 'computation'
- - xarray>=2022.12.0 ; extra == 'computation'
- - fsspec>=2022.11.0 ; extra == 'fss'
- - s3fs>=2022.11.0 ; extra == 'aws'
- - gcsfs>=2022.11.0 ; extra == 'gcp'
- - pandas-gbq>=0.19.0 ; extra == 'gcp'
- - odfpy>=1.4.1 ; extra == 'excel'
- - openpyxl>=3.1.0 ; extra == 'excel'
- - python-calamine>=0.1.7 ; extra == 'excel'
- - pyxlsb>=1.0.10 ; extra == 'excel'
- - xlrd>=2.0.1 ; extra == 'excel'
- - xlsxwriter>=3.0.5 ; extra == 'excel'
- - pyarrow>=10.0.1 ; extra == 'parquet'
- - pyarrow>=10.0.1 ; extra == 'feather'
- - tables>=3.8.0 ; extra == 'hdf5'
- - pyreadstat>=1.2.0 ; extra == 'spss'
- - sqlalchemy>=2.0.0 ; extra == 'postgresql'
- - psycopg2>=2.9.6 ; extra == 'postgresql'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql'
- - sqlalchemy>=2.0.0 ; extra == 'mysql'
- - pymysql>=1.0.2 ; extra == 'mysql'
- - sqlalchemy>=2.0.0 ; extra == 'sql-other'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other'
- - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other'
- - beautifulsoup4>=4.11.2 ; extra == 'html'
- - html5lib>=1.1 ; extra == 'html'
- - lxml>=4.9.2 ; extra == 'html'
- - lxml>=4.9.2 ; extra == 'xml'
- - matplotlib>=3.6.3 ; extra == 'plot'
- - jinja2>=3.1.2 ; extra == 'output-formatting'
- - tabulate>=0.9.0 ; extra == 'output-formatting'
- - pyqt5>=5.15.9 ; extra == 'clipboard'
- - qtpy>=2.3.0 ; extra == 'clipboard'
- - zstandard>=0.19.0 ; extra == 'compression'
- - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'all'
- - adbc-driver-sqlite>=0.8.0 ; extra == 'all'
- - beautifulsoup4>=4.11.2 ; extra == 'all'
- - bottleneck>=1.3.6 ; extra == 'all'
- - dataframe-api-compat>=0.1.7 ; extra == 'all'
- - fastparquet>=2022.12.0 ; extra == 'all'
- - fsspec>=2022.11.0 ; extra == 'all'
- - gcsfs>=2022.11.0 ; extra == 'all'
- - html5lib>=1.1 ; extra == 'all'
- - hypothesis>=6.46.1 ; extra == 'all'
- - jinja2>=3.1.2 ; extra == 'all'
- - lxml>=4.9.2 ; extra == 'all'
- - matplotlib>=3.6.3 ; extra == 'all'
- - numba>=0.56.4 ; extra == 'all'
- - numexpr>=2.8.4 ; extra == 'all'
- - odfpy>=1.4.1 ; extra == 'all'
- - openpyxl>=3.1.0 ; extra == 'all'
- - pandas-gbq>=0.19.0 ; extra == 'all'
- - psycopg2>=2.9.6 ; extra == 'all'
- - pyarrow>=10.0.1 ; extra == 'all'
- - pymysql>=1.0.2 ; extra == 'all'
- - pyqt5>=5.15.9 ; extra == 'all'
- - pyreadstat>=1.2.0 ; extra == 'all'
- - pytest>=7.3.2 ; extra == 'all'
- - pytest-xdist>=2.2.0 ; extra == 'all'
- - python-calamine>=0.1.7 ; extra == 'all'
- - pyxlsb>=1.0.10 ; extra == 'all'
- - qtpy>=2.3.0 ; extra == 'all'
- - scipy>=1.10.0 ; extra == 'all'
- - s3fs>=2022.11.0 ; extra == 'all'
- - sqlalchemy>=2.0.0 ; extra == 'all'
- - tables>=3.8.0 ; extra == 'all'
- - tabulate>=0.9.0 ; extra == 'all'
- - xarray>=2022.12.0 ; extra == 'all'
- - xlrd>=2.0.1 ; extra == 'all'
- - xlsxwriter>=3.0.5 ; extra == 'all'
- - zstandard>=0.19.0 ; extra == 'all'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
- name: pandas
- version: 2.3.3
- sha256: e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d
- requires_dist:
- - numpy>=1.22.4 ; python_full_version < '3.11'
- - numpy>=1.23.2 ; python_full_version == '3.11.*'
- - numpy>=1.26.0 ; python_full_version >= '3.12'
- - python-dateutil>=2.8.2
- - pytz>=2020.1
- - tzdata>=2022.7
- - hypothesis>=6.46.1 ; extra == 'test'
- - pytest>=7.3.2 ; extra == 'test'
- - pytest-xdist>=2.2.0 ; extra == 'test'
- - pyarrow>=10.0.1 ; extra == 'pyarrow'
- - bottleneck>=1.3.6 ; extra == 'performance'
- - numba>=0.56.4 ; extra == 'performance'
- - numexpr>=2.8.4 ; extra == 'performance'
- - scipy>=1.10.0 ; extra == 'computation'
- - xarray>=2022.12.0 ; extra == 'computation'
- - fsspec>=2022.11.0 ; extra == 'fss'
- - s3fs>=2022.11.0 ; extra == 'aws'
- - gcsfs>=2022.11.0 ; extra == 'gcp'
- - pandas-gbq>=0.19.0 ; extra == 'gcp'
- - odfpy>=1.4.1 ; extra == 'excel'
- - openpyxl>=3.1.0 ; extra == 'excel'
- - python-calamine>=0.1.7 ; extra == 'excel'
- - pyxlsb>=1.0.10 ; extra == 'excel'
- - xlrd>=2.0.1 ; extra == 'excel'
- - xlsxwriter>=3.0.5 ; extra == 'excel'
- - pyarrow>=10.0.1 ; extra == 'parquet'
- - pyarrow>=10.0.1 ; extra == 'feather'
- - tables>=3.8.0 ; extra == 'hdf5'
- - pyreadstat>=1.2.0 ; extra == 'spss'
- - sqlalchemy>=2.0.0 ; extra == 'postgresql'
- - psycopg2>=2.9.6 ; extra == 'postgresql'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql'
- - sqlalchemy>=2.0.0 ; extra == 'mysql'
- - pymysql>=1.0.2 ; extra == 'mysql'
- - sqlalchemy>=2.0.0 ; extra == 'sql-other'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other'
- - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other'
- - beautifulsoup4>=4.11.2 ; extra == 'html'
- - html5lib>=1.1 ; extra == 'html'
- - lxml>=4.9.2 ; extra == 'html'
- - lxml>=4.9.2 ; extra == 'xml'
- - matplotlib>=3.6.3 ; extra == 'plot'
- - jinja2>=3.1.2 ; extra == 'output-formatting'
- - tabulate>=0.9.0 ; extra == 'output-formatting'
- - pyqt5>=5.15.9 ; extra == 'clipboard'
- - qtpy>=2.3.0 ; extra == 'clipboard'
- - zstandard>=0.19.0 ; extra == 'compression'
- - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'all'
- - adbc-driver-sqlite>=0.8.0 ; extra == 'all'
- - beautifulsoup4>=4.11.2 ; extra == 'all'
- - bottleneck>=1.3.6 ; extra == 'all'
- - dataframe-api-compat>=0.1.7 ; extra == 'all'
- - fastparquet>=2022.12.0 ; extra == 'all'
- - fsspec>=2022.11.0 ; extra == 'all'
- - gcsfs>=2022.11.0 ; extra == 'all'
- - html5lib>=1.1 ; extra == 'all'
- - hypothesis>=6.46.1 ; extra == 'all'
- - jinja2>=3.1.2 ; extra == 'all'
- - lxml>=4.9.2 ; extra == 'all'
- - matplotlib>=3.6.3 ; extra == 'all'
- - numba>=0.56.4 ; extra == 'all'
- - numexpr>=2.8.4 ; extra == 'all'
- - odfpy>=1.4.1 ; extra == 'all'
- - openpyxl>=3.1.0 ; extra == 'all'
- - pandas-gbq>=0.19.0 ; extra == 'all'
- - psycopg2>=2.9.6 ; extra == 'all'
- - pyarrow>=10.0.1 ; extra == 'all'
- - pymysql>=1.0.2 ; extra == 'all'
- - pyqt5>=5.15.9 ; extra == 'all'
- - pyreadstat>=1.2.0 ; extra == 'all'
- - pytest>=7.3.2 ; extra == 'all'
- - pytest-xdist>=2.2.0 ; extra == 'all'
- - python-calamine>=0.1.7 ; extra == 'all'
- - pyxlsb>=1.0.10 ; extra == 'all'
- - qtpy>=2.3.0 ; extra == 'all'
- - scipy>=1.10.0 ; extra == 'all'
- - s3fs>=2022.11.0 ; extra == 'all'
- - sqlalchemy>=2.0.0 ; extra == 'all'
- - tables>=3.8.0 ; extra == 'all'
- - tabulate>=0.9.0 ; extra == 'all'
- - xarray>=2022.12.0 ; extra == 'all'
- - xlrd>=2.0.1 ; extra == 'all'
- - xlsxwriter>=3.0.5 ; extra == 'all'
- - zstandard>=0.19.0 ; extra == 'all'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl
- name: pandas
- version: 2.3.3
- sha256: bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8
- requires_dist:
- - numpy>=1.22.4 ; python_full_version < '3.11'
- - numpy>=1.23.2 ; python_full_version == '3.11.*'
- - numpy>=1.26.0 ; python_full_version >= '3.12'
- - python-dateutil>=2.8.2
- - pytz>=2020.1
- - tzdata>=2022.7
- - hypothesis>=6.46.1 ; extra == 'test'
- - pytest>=7.3.2 ; extra == 'test'
- - pytest-xdist>=2.2.0 ; extra == 'test'
- - pyarrow>=10.0.1 ; extra == 'pyarrow'
- - bottleneck>=1.3.6 ; extra == 'performance'
- - numba>=0.56.4 ; extra == 'performance'
- - numexpr>=2.8.4 ; extra == 'performance'
- - scipy>=1.10.0 ; extra == 'computation'
- - xarray>=2022.12.0 ; extra == 'computation'
- - fsspec>=2022.11.0 ; extra == 'fss'
- - s3fs>=2022.11.0 ; extra == 'aws'
- - gcsfs>=2022.11.0 ; extra == 'gcp'
- - pandas-gbq>=0.19.0 ; extra == 'gcp'
- - odfpy>=1.4.1 ; extra == 'excel'
- - openpyxl>=3.1.0 ; extra == 'excel'
- - python-calamine>=0.1.7 ; extra == 'excel'
- - pyxlsb>=1.0.10 ; extra == 'excel'
- - xlrd>=2.0.1 ; extra == 'excel'
- - xlsxwriter>=3.0.5 ; extra == 'excel'
- - pyarrow>=10.0.1 ; extra == 'parquet'
- - pyarrow>=10.0.1 ; extra == 'feather'
- - tables>=3.8.0 ; extra == 'hdf5'
- - pyreadstat>=1.2.0 ; extra == 'spss'
- - sqlalchemy>=2.0.0 ; extra == 'postgresql'
- - psycopg2>=2.9.6 ; extra == 'postgresql'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql'
- - sqlalchemy>=2.0.0 ; extra == 'mysql'
- - pymysql>=1.0.2 ; extra == 'mysql'
- - sqlalchemy>=2.0.0 ; extra == 'sql-other'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other'
- - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other'
- - beautifulsoup4>=4.11.2 ; extra == 'html'
- - html5lib>=1.1 ; extra == 'html'
- - lxml>=4.9.2 ; extra == 'html'
- - lxml>=4.9.2 ; extra == 'xml'
- - matplotlib>=3.6.3 ; extra == 'plot'
- - jinja2>=3.1.2 ; extra == 'output-formatting'
- - tabulate>=0.9.0 ; extra == 'output-formatting'
- - pyqt5>=5.15.9 ; extra == 'clipboard'
- - qtpy>=2.3.0 ; extra == 'clipboard'
- - zstandard>=0.19.0 ; extra == 'compression'
- - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard'
- - adbc-driver-postgresql>=0.8.0 ; extra == 'all'
- - adbc-driver-sqlite>=0.8.0 ; extra == 'all'
- - beautifulsoup4>=4.11.2 ; extra == 'all'
- - bottleneck>=1.3.6 ; extra == 'all'
- - dataframe-api-compat>=0.1.7 ; extra == 'all'
- - fastparquet>=2022.12.0 ; extra == 'all'
- - fsspec>=2022.11.0 ; extra == 'all'
- - gcsfs>=2022.11.0 ; extra == 'all'
- - html5lib>=1.1 ; extra == 'all'
- - hypothesis>=6.46.1 ; extra == 'all'
- - jinja2>=3.1.2 ; extra == 'all'
- - lxml>=4.9.2 ; extra == 'all'
- - matplotlib>=3.6.3 ; extra == 'all'
- - numba>=0.56.4 ; extra == 'all'
- - numexpr>=2.8.4 ; extra == 'all'
- - odfpy>=1.4.1 ; extra == 'all'
- - openpyxl>=3.1.0 ; extra == 'all'
- - pandas-gbq>=0.19.0 ; extra == 'all'
- - psycopg2>=2.9.6 ; extra == 'all'
- - pyarrow>=10.0.1 ; extra == 'all'
- - pymysql>=1.0.2 ; extra == 'all'
- - pyqt5>=5.15.9 ; extra == 'all'
- - pyreadstat>=1.2.0 ; extra == 'all'
- - pytest>=7.3.2 ; extra == 'all'
- - pytest-xdist>=2.2.0 ; extra == 'all'
- - python-calamine>=0.1.7 ; extra == 'all'
- - pyxlsb>=1.0.10 ; extra == 'all'
- - qtpy>=2.3.0 ; extra == 'all'
- - scipy>=1.10.0 ; extra == 'all'
- - s3fs>=2022.11.0 ; extra == 'all'
- - sqlalchemy>=2.0.0 ; extra == 'all'
- - tables>=3.8.0 ; extra == 'all'
- - tabulate>=0.9.0 ; extra == 'all'
- - xarray>=2022.12.0 ; extra == 'all'
- - xlrd>=2.0.1 ; extra == 'all'
- - xlsxwriter>=3.0.5 ; extra == 'all'
- - zstandard>=0.19.0 ; extra == 'all'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
- name: patsy
- version: 1.0.2
- sha256: 37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a
- requires_dist:
- - numpy>=1.4
- - pytest ; extra == 'test'
- - pytest-cov ; extra == 'test'
- - scipy ; extra == 'test'
- requires_python: '>=3.6'
-- pypi: https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: pillow
- version: 12.1.0
- sha256: 6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc
- requires_dist:
- - furo ; extra == 'docs'
- - olefile ; extra == 'docs'
- - sphinx>=8.2 ; extra == 'docs'
- - sphinx-autobuild ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - sphinx-inline-tabs ; extra == 'docs'
- - sphinxext-opengraph ; extra == 'docs'
- - olefile ; extra == 'fpx'
- - olefile ; extra == 'mic'
- - arro3-compute ; extra == 'test-arrow'
- - arro3-core ; extra == 'test-arrow'
- - nanoarrow ; extra == 'test-arrow'
- - pyarrow ; extra == 'test-arrow'
- - check-manifest ; extra == 'tests'
- - coverage>=7.4.2 ; extra == 'tests'
- - defusedxml ; extra == 'tests'
- - markdown2 ; extra == 'tests'
- - olefile ; extra == 'tests'
- - packaging ; extra == 'tests'
- - pyroma>=5 ; extra == 'tests'
- - pytest ; extra == 'tests'
- - pytest-cov ; extra == 'tests'
- - pytest-timeout ; extra == 'tests'
- - pytest-xdist ; extra == 'tests'
- - trove-classifiers>=2024.10.12 ; extra == 'tests'
- - defusedxml ; extra == 'xmp'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- name: pillow
- version: 12.1.0
- sha256: e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c
- requires_dist:
- - furo ; extra == 'docs'
- - olefile ; extra == 'docs'
- - sphinx>=8.2 ; extra == 'docs'
- - sphinx-autobuild ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - sphinx-inline-tabs ; extra == 'docs'
- - sphinxext-opengraph ; extra == 'docs'
- - olefile ; extra == 'fpx'
- - olefile ; extra == 'mic'
- - arro3-compute ; extra == 'test-arrow'
- - arro3-core ; extra == 'test-arrow'
- - nanoarrow ; extra == 'test-arrow'
- - pyarrow ; extra == 'test-arrow'
- - check-manifest ; extra == 'tests'
- - coverage>=7.4.2 ; extra == 'tests'
- - defusedxml ; extra == 'tests'
- - markdown2 ; extra == 'tests'
- - olefile ; extra == 'tests'
- - packaging ; extra == 'tests'
- - pyroma>=5 ; extra == 'tests'
- - pytest ; extra == 'tests'
- - pytest-cov ; extra == 'tests'
- - pytest-timeout ; extra == 'tests'
- - pytest-xdist ; extra == 'tests'
- - trove-classifiers>=2024.10.12 ; extra == 'tests'
- - defusedxml ; extra == 'xmp'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl
- name: pillow
- version: 12.1.0
- sha256: db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac
- requires_dist:
- - furo ; extra == 'docs'
- - olefile ; extra == 'docs'
- - sphinx>=8.2 ; extra == 'docs'
- - sphinx-autobuild ; extra == 'docs'
- - sphinx-copybutton ; extra == 'docs'
- - sphinx-inline-tabs ; extra == 'docs'
- - sphinxext-opengraph ; extra == 'docs'
- - olefile ; extra == 'fpx'
- - olefile ; extra == 'mic'
- - arro3-compute ; extra == 'test-arrow'
- - arro3-core ; extra == 'test-arrow'
- - nanoarrow ; extra == 'test-arrow'
- - pyarrow ; extra == 'test-arrow'
- - check-manifest ; extra == 'tests'
- - coverage>=7.4.2 ; extra == 'tests'
- - defusedxml ; extra == 'tests'
- - markdown2 ; extra == 'tests'
- - olefile ; extra == 'tests'
- - packaging ; extra == 'tests'
- - pyroma>=5 ; extra == 'tests'
- - pytest ; extra == 'tests'
- - pytest-cov ; extra == 'tests'
- - pytest-timeout ; extra == 'tests'
- - pytest-xdist ; extra == 'tests'
- - trove-classifiers>=2024.10.12 ; extra == 'tests'
- - defusedxml ; extra == 'xmp'
- requires_python: '>=3.10'
-- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
- sha256: 04c64fb78c520e5c396b6e07bc9082735a5cc28175dbe23138201d0a9441800b
- md5: 1bd2e65c8c7ef24f4639ae6e850dacc2
+ - pkg:pypi/kiwisolver?source=hash-mapping
+ size: 82688
+ timestamp: 1762488927391
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/kiwisolver-1.4.9-py312hd8c8125_2.conda
+ sha256: 8d68f6ec4d947902034fe9ed9d4a4c1180b5767bd9731af940f5a0e436bc3dfd
+ md5: ddf4775023a2466ee308792ed80ca408
depends:
- - python >=3.10
- python
+ - python 3.12.* *_cpython
+ - libcxx >=19
+ - __osx >=11.0
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/kiwisolver?source=hash-mapping
+ size: 67752
+ timestamp: 1762488827477
+- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda
+ sha256: 99df692f7a8a5c27cd14b5fb1374ee55e756631b9c3d659ed3ee60830249b238
+ md5: 3f43953b7d3fb3aaa1d0d0723d91e368
+ depends:
+ - keyutils >=1.6.1,<2.0a0
+ - libedit >=3.1.20191231,<3.2.0a0
+ - libedit >=3.1.20191231,<4.0a0
+ - libgcc-ng >=12
+ - libstdcxx-ng >=12
+ - openssl >=3.3.1,<4.0a0
license: MIT
license_family: MIT
- purls:
- - pkg:pypi/platformdirs?source=hash-mapping
- size: 23922
- timestamp: 1764950726246
-- pypi: https://files.pythonhosted.org/packages/e7/c3/3031c931098de393393e1f93a38dc9ed6805d86bb801acc3cf2d5bd1e6b7/plotly-6.5.0-py3-none-any.whl
- name: plotly
- version: 6.5.0
- sha256: 5ac851e100367735250206788a2b1325412aa4a4917a4fe3e6f0bc5aa6f3d90a
- requires_dist:
- - narwhals>=1.15.1
- - packaging
- - numpy ; extra == 'express'
- - kaleido>=1.1.0 ; extra == 'kaleido'
- - pytest ; extra == 'dev-core'
- - requests ; extra == 'dev-core'
- - ruff==0.11.12 ; extra == 'dev-core'
- - plotly[dev-core] ; extra == 'dev-build'
- - build ; extra == 'dev-build'
- - jupyter ; extra == 'dev-build'
- - plotly[dev-build] ; extra == 'dev-optional'
- - plotly[kaleido] ; extra == 'dev-optional'
- - anywidget ; extra == 'dev-optional'
- - colorcet ; extra == 'dev-optional'
- - fiona<=1.9.6 ; python_full_version < '3.9' and extra == 'dev-optional'
- - geopandas ; extra == 'dev-optional'
- - inflect ; extra == 'dev-optional'
- - numpy ; extra == 'dev-optional'
- - orjson ; extra == 'dev-optional'
- - pandas ; extra == 'dev-optional'
- - pdfrw ; extra == 'dev-optional'
- - pillow ; extra == 'dev-optional'
- - plotly-geo ; extra == 'dev-optional'
- - polars[timezone] ; extra == 'dev-optional'
- - pyarrow ; extra == 'dev-optional'
- - pyshp ; extra == 'dev-optional'
- - pytz ; extra == 'dev-optional'
- - scikit-image ; extra == 'dev-optional'
- - scipy ; extra == 'dev-optional'
- - shapely ; extra == 'dev-optional'
- - statsmodels ; extra == 'dev-optional'
- - vaex ; python_full_version < '3.10' and extra == 'dev-optional'
- - xarray ; extra == 'dev-optional'
- - plotly[dev-optional] ; extra == 'dev'
- requires_python: '>=3.8'
-- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
- sha256: e14aafa63efa0528ca99ba568eaf506eb55a0371d12e6250aaaa61718d2eb62e
- md5: d7585b6550ad04c8c5e21097ada2888e
+ purls: []
+ size: 1370023
+ timestamp: 1719463201255
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.3-h50a48e9_0.conda
+ sha256: 0ec272afcf7ea7fbf007e07a3b4678384b7da4047348107b2ae02630a570a815
+ md5: 29c10432a2ca1472b53f299ffb2ffa37
depends:
- - python >=3.9
- - python
+ - keyutils >=1.6.1,<2.0a0
+ - libedit >=3.1.20191231,<3.2.0a0
+ - libedit >=3.1.20191231,<4.0a0
+ - libgcc-ng >=12
+ - libstdcxx-ng >=12
+ - openssl >=3.3.1,<4.0a0
license: MIT
license_family: MIT
- purls:
- - pkg:pypi/pluggy?source=compressed-mapping
- size: 25877
- timestamp: 1764896838868
-- pypi: ./
- name: preface
- version: 1.0.0.dev0
- sha256: 6682492844d8a0a8cf33b43218e4bb1b4501ac723375e8697f7bf1a202889956
- requires_dist:
- - pandas>=2.3.3,<3
- - numpy>=2.4.0,<3
- - scikit-learn>=1.8.0,<2
- - tensorflow>=2.20.0,<3
- - matplotlib>=3.10.8,<4
- - statsmodels>=0.14.6,<0.15
- - typer>=0.21.0,<0.22
- - rich>=14.2.0,<15
- - xgboost>=3.1.2,<4
- - optuna>=4.6.0,<5
- - optuna-integration[tfkeras]>=4.6.0,<5
- - plotly>=6.5.0,<7
- - kaleido>=1.2.0,<2
- - onnx>=1.20.0,<2
- - onnxmltools>=1.14.0,<2
- - skl2onnx>=1.19.1,<2
- - onnxconverter-common>=1.16.0,<2
- - onnxruntime>=1.23.2,<2
- - tf2onnx>=1.8.4,<2
- requires_python: '>=3.11,<3.14'
-- pypi: https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl
- name: protobuf
- version: 6.33.2
- sha256: 1f8017c48c07ec5859106533b682260ba3d7c5567b1ca1f24297ce03384d1b4f
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl
- name: protobuf
- version: 6.33.2
- sha256: b5d3b5625192214066d99b2b605f5783483575656784de223f00a8d00754fc0e
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl
- name: protobuf
- version: 6.33.2
- sha256: d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43
- requires_python: '>=3.9'
-- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
- sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a
- md5: 6b6ece66ebcae2d5f326c77ef2c5a066
+ purls: []
+ size: 1474620
+ timestamp: 1719463205834
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.3-h237132a_0.conda
+ sha256: 4442f957c3c77d69d9da3521268cad5d54c9033f1a73f99cde0a3658937b159b
+ md5: c6dc8a0fdec13a0565936655c33069a1
depends:
- - python >=3.9
- license: BSD-2-Clause
- license_family: BSD
- purls:
- - pkg:pypi/pygments?source=hash-mapping
- size: 889287
- timestamp: 1750615908735
-- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
- sha256: ad0bb78785ab385d0afcca4a55e0226d8e6710ebad6450caa552f5fe61c2f6a0
- md5: 3a830511a81b99b67a1206a9d29b44b3
+ - __osx >=11.0
+ - libcxx >=16
+ - libedit >=3.1.20191231,<3.2.0a0
+ - libedit >=3.1.20191231,<4.0a0
+ - openssl >=3.3.1,<4.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 1155530
+ timestamp: 1719463474401
+- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.17-h717163a_0.conda
+ sha256: d6a61830a354da022eae93fa896d0991385a875c6bba53c82263a289deda9db8
+ md5: 000e85703f0fd9594c81710dd5066471
depends:
- - astroid >=4.0.2,<=4.1.0.dev0
- - colorama >=0.4.5
- - isort >=5,<8,!=5.13
- - mccabe >=0.6,<0.8
- - platformdirs >=2.2
- - python >=3.10
- - tomli >=1.1.0
- - tomlkit >=0.10.1
- - dill >=0.3.7
- - python
- license: GPL-2.0-or-later
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libjpeg-turbo >=3.0.0,<4.0a0
+ - libtiff >=4.7.0,<4.8.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 248046
+ timestamp: 1739160907615
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.17-hc88f144_0.conda
+ sha256: 47cf6a4780dc41caa9bc95f020eed485b07010c9ccc85e9ef44b538fedb5341d
+ md5: b87b1abd2542cf65a00ad2e2461a3083
+ depends:
+ - libgcc >=13
+ - libjpeg-turbo >=3.0.0,<4.0a0
+ - libtiff >=4.7.0,<4.8.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 287007
+ timestamp: 1739161069194
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lcms2-2.17-h7eeda09_0.conda
+ sha256: 310a62c2f074ebd5aa43b3cd4b00d46385ce680fa2132ecee255a200e2d2f15f
+ md5: 92a61fd30b19ebd5c1621a5bfe6d8b5f
+ depends:
+ - __osx >=11.0
+ - libjpeg-turbo >=3.0.0,<4.0a0
+ - libtiff >=4.7.0,<4.8.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 212125
+ timestamp: 1739161108467
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45-default_hbd61a6d_105.conda
+ sha256: 1027bd8aa0d5144e954e426ab6218fd5c14e54a98f571985675468b339c808ca
+ md5: 3ec0aa5037d39b06554109a01e6fb0c6
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - zstd >=1.5.7,<1.6.0a0
+ constrains:
+ - binutils_impl_linux-64 2.45
+ license: GPL-3.0-only
license_family: GPL
- purls:
- - pkg:pypi/pylint?source=hash-mapping
- size: 390859
- timestamp: 1764517517150
-- pypi: https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl
- name: pyparsing
- version: 3.3.1
- sha256: 023b5e7e5520ad96642e2c6db4cb683d3970bd640cdf7115049a6e9c3682df82
- requires_dist:
- - railroad-diagrams ; extra == 'diagrams'
- - jinja2 ; extra == 'diagrams'
- requires_python: '>=3.9'
-- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhcf101f3_1.conda
- sha256: 39f41a52eb6f927caf5cd42a2ff98a09bb850ce9758b432869374b6253826962
- md5: da0c42269086f5170e2b296878ec13a6
+ purls: []
+ size: 730831
+ timestamp: 1766513089214
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45-default_h1979696_105.conda
+ sha256: 12e7341b89e9ea319a3b4de03d02cd988fa02b8a678f4e46779515009b5e475c
+ md5: 849c4cbbf8dd1d71e66c13afed1d2f12
depends:
- - pygments >=2.7.2
- - python >=3.10
- - iniconfig >=1
- - packaging >=20
- - pluggy >=1.5,<2
- - tomli >=1
- - colorama >=0.4
- - exceptiongroup >=1
- - python
+ - zstd >=1.5.7,<1.6.0a0
constrains:
- - pytest-faulthandler >=2
+ - binutils_impl_linux-aarch64 2.45
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 876257
+ timestamp: 1766513180236
+- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda
+ sha256: 412381a43d5ff9bbed82cd52a0bbca5b90623f62e41007c9c42d3870c60945ff
+ md5: 9344155d33912347b37f0ae6c410a835
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libstdcxx >=13
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 264243
+ timestamp: 1745264221534
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.0.0-hfdc4d58_1.conda
+ sha256: f01df5bbf97783fac9b89be602b4d02f94353f5221acfd80c424ec1c9a8d276c
+ md5: 60dceb7e876f4d74a9cbd42bbbc6b9cf
+ depends:
+ - libgcc >=13
+ - libstdcxx >=13
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 227184
+ timestamp: 1745265544057
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lerc-4.0.0-hd64df32_1.conda
+ sha256: 12361697f8ffc9968907d1a7b5830e34c670e4a59b638117a2cdfed8f63a38f8
+ md5: a74332d9b60b62905e3d30709df08bf1
+ depends:
+ - __osx >=11.0
+ - libcxx >=18
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 188306
+ timestamp: 1745264362794
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20250512.1-cxx17_hba17884_0.conda
+ sha256: dcd1429a1782864c452057a6c5bc1860f2b637dc20a2b7e6eacd57395bbceff8
+ md5: 83b160d4da3e1e847bf044997621ed63
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libstdcxx >=13
+ constrains:
+ - libabseil-static =20250512.1=cxx17*
+ - abseil-cpp =20250512.1
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 1310612
+ timestamp: 1750194198254
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20240722.0-cxx17_h18dbdb1_4.conda
+ sha256: bb6c5fb3b8de5f90735c5252b57efb3c268ee222c755569dac18065f05147670
+ md5: 633b9fe454ffea2aaf29e191d946a83b
+ depends:
+ - libgcc >=13
+ - libstdcxx >=13
+ constrains:
+ - abseil-cpp =20240722.0
+ - libabseil-static =20240722.0=cxx17*
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 1334844
+ timestamp: 1736008472455
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240722.0-cxx17_h07bc746_4.conda
+ sha256: 05fa5e5e908962b9c5aba95f962e2ca81d9599c4715aebe5e4ddb72b309d1770
+ md5: c2d95bd7aa8d564a9bd7eca5e571a5b3
+ depends:
+ - __osx >=11.0
+ - libcxx >=18
+ constrains:
+ - libabseil-static =20240722.0=cxx17*
+ - abseil-cpp =20240722.0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 1178260
+ timestamp: 1736008642885
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.4-h3f801dc_0.conda
+ sha256: 410ab78fe89bc869d435de04c9ffa189598ac15bb0fe1ea8ace8fb1b860a2aa3
+ md5: 01ba04e414e47f95c03d6ddd81fd37be
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libstdcxx >=13
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 36825
+ timestamp: 1749993532943
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libaec-1.1.4-h1e66f74_0.conda
+ sha256: 891844586d02bb528c18fddc6aa14dfd995532fbb8795156d215318e1de242f7
+ md5: 6360d4091c919d6e185f1fc3ac36716e
+ depends:
+ - libgcc >=13
+ - libstdcxx >=13
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 36847
+ timestamp: 1749993545798
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libaec-1.1.4-h51d1e36_0.conda
+ sha256: 0ea6b73b3fb1511615d9648186a7409e73b7a8d9b3d890d39df797730e3d1dbb
+ md5: 8ed0f86b7a5529b98ec73b43a53ce800
+ depends:
+ - __osx >=11.0
+ - libcxx >=18
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 30173
+ timestamp: 1749993648288
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda
+ build_number: 5
+ sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c
+ md5: c160954f7418d7b6e87eaf05a8913fa9
+ depends:
+ - libopenblas >=0.3.30,<0.3.31.0a0
+ - libopenblas >=0.3.30,<1.0a0
+ constrains:
+ - mkl <2026
+ - liblapack 3.11.0 5*_openblas
+ - libcblas 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ - liblapacke 3.11.0 5*_openblas
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18213
+ timestamp: 1765818813880
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda
+ build_number: 5
+ sha256: 700f3c03d0fba8e687a345404a45fbabe781c1cf92242382f62cef2948745ec4
+ md5: 5afcea37a46f76ec1322943b3c4dfdc0
+ depends:
+ - libopenblas >=0.3.30,<0.3.31.0a0
+ - libopenblas >=0.3.30,<1.0a0
+ constrains:
+ - mkl <2026
+ - libcblas 3.11.0 5*_openblas
+ - liblapack 3.11.0 5*_openblas
+ - liblapacke 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18369
+ timestamp: 1765818610617
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda
+ build_number: 5
+ sha256: 620a6278f194dcabc7962277da6835b1e968e46ad0c8e757736255f5ddbfca8d
+ md5: bcc025e2bbaf8a92982d20863fe1fb69
+ depends:
+ - libopenblas >=0.3.30,<0.3.31.0a0
+ - libopenblas >=0.3.30,<1.0a0
+ constrains:
+ - libcblas 3.11.0 5*_openblas
+ - liblapack 3.11.0 5*_openblas
+ - liblapacke 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ - mkl <2026
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18546
+ timestamp: 1765819094137
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda
+ sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e
+ md5: 72c8fd1af66bd67bf580645b426513ed
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
license: MIT
license_family: MIT
- purls:
- - pkg:pypi/pytest?source=hash-mapping
- size: 294852
- timestamp: 1762354779909
-- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
- sha256: 218306243faf3c36347131c2b36bb189daa948ac2e92c7ab52bb26cc8c157b3c
- md5: c54c0107057d67ddf077751339ec2c63
+ purls: []
+ size: 79965
+ timestamp: 1764017188531
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.2.0-he30d5cf_1.conda
+ sha256: 5fa8c163c8d776503aa68cdaf798ff9440c76a0a1c3ea84e0c43dbf1ece8af4d
+ md5: 8ec1d03f3000108899d1799d9964f281
depends:
- - coverage >=5.2.1
- - pytest >=4.6
- - python >=3.8
- - toml
+ - libgcc >=14
license: MIT
license_family: MIT
- purls:
- - pkg:pypi/pytest-cov?source=hash-mapping
- size: 25507
- timestamp: 1711411153367
-- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
- name: pytest-timeout
- version: 2.4.0
- sha256: c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2
- requires_dist:
- - pytest>=7.0.0
- requires_python: '>=3.7'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.11-hc97d973_100_cp313.conda
- build_number: 100
- sha256: 9cf014cf28e93ee242bacfbf664e8b45ae06e50b04291e640abeaeb0cba0364c
- md5: 0cbb0010f1d8ecb64a428a8d4214609e
+ purls: []
+ size: 80030
+ timestamp: 1764017273715
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda
+ sha256: a7cb9e660531cf6fbd4148cff608c85738d0b76f0975c5fc3e7d5e92840b7229
+ md5: 006e7ddd8a110771134fcc4e1e3a6ffa
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 79443
+ timestamp: 1764017945924
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda
+ sha256: 12fff21d38f98bc446d82baa890e01fd82e3b750378fedc720ff93522ffb752b
+ md5: 366b40a69f0ad6072561c1d09301c886
depends:
- __glibc >=2.17,<3.0.a0
- - bzip2 >=1.0.8,<2.0a0
- - ld_impl_linux-64 >=2.36.1
- - libexpat >=2.7.3,<3.0a0
- - libffi >=3.5.2,<3.6.0a0
+ - libbrotlicommon 1.2.0 hb03c661_1
- libgcc >=14
- - liblzma >=5.8.1,<6.0a0
- - libmpdec >=4.0.0,<5.0a0
- - libsqlite >=3.51.1,<4.0a0
- - libuuid >=2.41.2,<3.0a0
- - libzlib >=1.3.1,<2.0a0
- - ncurses >=6.5,<7.0a0
- - openssl >=3.5.4,<4.0a0
- - python_abi 3.13.* *_cp313
- - readline >=8.2,<9.0a0
- - tk >=8.6.13,<8.7.0a0
- - tzdata
- license: Python-2.0
+ license: MIT
+ license_family: MIT
purls: []
- size: 37226336
- timestamp: 1765021889577
- python_site_packages_path: lib/python3.13/site-packages
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.13.11-h4c0d347_100_cp313.conda
- build_number: 100
- sha256: bbb0b341c3ce460d02087e1c5e0d3bb814c270f4ae61f82c0e2996ec3902d301
- md5: a6e2b5b263090516ec36efdd51dcc35b
+ size: 34632
+ timestamp: 1764017199083
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.2.0-he30d5cf_1.conda
+ sha256: 494365e8f58799ea95a6e82334ef696e9c2120aecd6626121694b30a15033301
+ md5: 47e5b71b77bb8b47b4ecf9659492977f
depends:
- - bzip2 >=1.0.8,<2.0a0
- - ld_impl_linux-aarch64 >=2.36.1
- - libexpat >=2.7.3,<3.0a0
- - libffi >=3.5.2,<3.6.0a0
+ - libbrotlicommon 1.2.0 he30d5cf_1
- libgcc >=14
- - liblzma >=5.8.1,<6.0a0
- - libmpdec >=4.0.0,<5.0a0
- - libsqlite >=3.51.1,<4.0a0
- - libuuid >=2.41.2,<3.0a0
- - libzlib >=1.3.1,<2.0a0
- - ncurses >=6.5,<7.0a0
- - openssl >=3.5.4,<4.0a0
- - python_abi 3.13.* *_cp313
- - readline >=8.2,<9.0a0
- - tk >=8.6.13,<8.7.0a0
- - tzdata
- license: Python-2.0
+ license: MIT
+ license_family: MIT
purls: []
- size: 33896215
- timestamp: 1765020450426
- python_site_packages_path: lib/python3.13/site-packages
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.11-hfc2f54d_100_cp313.conda
- build_number: 100
- sha256: c476f4e9b6d97c46b496b442878924868a54e5727251549ebfc82027aa52af68
- md5: 18a8c69608151098a8fb75eea64cc266
+ size: 33166
+ timestamp: 1764017282936
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda
+ sha256: 2eae444039826db0454b19b52a3390f63bfe24f6b3e63089778dd5a5bf48b6bf
+ md5: 079e88933963f3f149054eec2c487bc2
depends:
- __osx >=11.0
- - bzip2 >=1.0.8,<2.0a0
- - libexpat >=2.7.3,<3.0a0
- - libffi >=3.5.2,<3.6.0a0
- - liblzma >=5.8.1,<6.0a0
- - libmpdec >=4.0.0,<5.0a0
- - libsqlite >=3.51.1,<4.0a0
- - libzlib >=1.3.1,<2.0a0
- - ncurses >=6.5,<7.0a0
- - openssl >=3.5.4,<4.0a0
- - python_abi 3.13.* *_cp313
- - readline >=8.2,<9.0a0
- - tk >=8.6.13,<8.7.0a0
- - tzdata
- license: Python-2.0
+ - libbrotlicommon 1.2.0 hc919400_1
+ license: MIT
+ license_family: MIT
purls: []
- size: 12920650
- timestamp: 1765020887340
- python_site_packages_path: lib/python3.13/site-packages
-- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- name: python-dateutil
- version: 2.9.0.post0
- sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
- requires_dist:
- - six>=1.5
- requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
-- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda
- build_number: 8
- sha256: 210bffe7b121e651419cb196a2a63687b087497595c9be9d20ebe97dd06060a7
- md5: 94305520c52a4aa3f6c2b1ff6008d9f8
+ size: 29452
+ timestamp: 1764017979099
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda
+ sha256: a0c15c79997820bbd3fbc8ecf146f4fe0eca36cc60b62b63ac6cf78857f1dd0d
+ md5: 4ffbb341c8b616aa2494b6afb26a0c5f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libbrotlicommon 1.2.0 hb03c661_1
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 298378
+ timestamp: 1764017210931
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.2.0-he30d5cf_1.conda
+ sha256: f998c03257b9aa1f7464446af2cf424862f0e54258a2a588309853e45ae771df
+ md5: 6553a5d017fe14859ea8a4e6ea5def8f
+ depends:
+ - libbrotlicommon 1.2.0 he30d5cf_1
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 309304
+ timestamp: 1764017292044
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda
+ sha256: 01436c32bb41f9cb4bcf07dda647ce4e5deb8307abfc3abdc8da5317db8189d1
+ md5: b2b7c8288ca1a2d71ff97a8e6a1e8883
+ depends:
+ - __osx >=11.0
+ - libbrotlicommon 1.2.0 hc919400_1
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 290754
+ timestamp: 1764018009077
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda
+ build_number: 5
+ sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8
+ md5: 6636a2b6f1a87572df2970d3ebc87cc0
+ depends:
+ - libblas 3.11.0 5_h4a7cf45_openblas
constrains:
- - python 3.13.* *_cp313
+ - liblapacke 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ - liblapack 3.11.0 5*_openblas
license: BSD-3-Clause
license_family: BSD
purls: []
- size: 7002
- timestamp: 1752805902938
-- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- name: pytz
- version: '2025.2'
- sha256: 5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
-- pypi: https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: pyyaml
- version: 6.0.3
- sha256: ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- name: pyyaml
- version: 6.0.3
- sha256: 0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl
- name: pyyaml
- version: 6.0.3
- sha256: 2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1
- requires_python: '>=3.8'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
- sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002
- md5: d7d95fc8287ea7bf33e0e7116d2b95ec
+ size: 18194
+ timestamp: 1765818837135
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda
+ build_number: 5
+ sha256: 3fad5c9de161dccb4e42c8b1ae8eccb33f4ed56bccbcced9cbb0956ae7869e61
+ md5: 0b2f1143ae2d0aa4c991959d0daaf256
+ depends:
+ - libblas 3.11.0 5_haddc8a3_openblas
+ constrains:
+ - liblapack 3.11.0 5*_openblas
+ - liblapacke 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18371
+ timestamp: 1765818618899
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda
+ build_number: 5
+ sha256: 38809c361bbd165ecf83f7f05fae9b791e1baa11e4447367f38ae1327f402fc0
+ md5: efd8bd15ca56e9d01748a3beab8404eb
+ depends:
+ - libblas 3.11.0 5_h51639a9_openblas
+ constrains:
+ - liblapacke 3.11.0 5*_openblas
+ - liblapack 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18548
+ timestamp: 1765819108956
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.7-default_h99862b1_3.conda
+ sha256: 4353a2695290716fdc85821936aaa0bacacf59ae91f65708921b753bfa2d2a2f
+ md5: b450493426793d5fe7d8216a27120050
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=14
- - ncurses >=6.5,<7.0a0
- license: GPL-3.0-only
- license_family: GPL
+ - libllvm21 >=21.1.7,<21.2.0a0
+ - libstdcxx >=14
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
purls: []
- size: 345073
- timestamp: 1765813471974
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda
- sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216
- md5: 3d49cad61f829f4f0e0611547a9cda12
+ size: 21055419
+ timestamp: 1767059401369
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp21.1-21.1.7-default_he95a3c9_3.conda
+ sha256: f66fd82f45079c2e325e6a0d18fade22cf80d687f27ee514a7f41cd15423c04f
+ md5: 71a8b7c6439119fcb9a555127d149a1a
depends:
- libgcc >=14
- - ncurses >=6.5,<7.0a0
- license: GPL-3.0-only
- license_family: GPL
+ - libllvm21 >=21.1.7,<21.2.0a0
+ - libstdcxx >=14
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
purls: []
- size: 357597
- timestamp: 1765815673644
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
- sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477
- md5: f8381319127120ce51e081dce4865cf4
+ size: 20647886
+ timestamp: 1767060409837
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-21.1.7-default_h746c552_3.conda
+ sha256: bdb778b01a7d60aa8cd1c56c613ac8123b0c646793017fda11f27b71c7bd94bf
+ md5: ee42c44c3676cdbb6e63190077ca57d3
depends:
- - __osx >=11.0
- - ncurses >=6.5,<7.0a0
- license: GPL-3.0-only
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libllvm21 >=21.1.7,<21.2.0a0
+ - libstdcxx >=14
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
+ purls: []
+ size: 12347163
+ timestamp: 1767059745824
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-21.1.7-default_h94a09a5_3.conda
+ sha256: 679213196dedc9bf4dbc0c5ba9974a6e3523805a51b624825ac796df58018745
+ md5: b60f2316d922a558baa84ad24306bfc4
+ depends:
+ - libgcc >=14
+ - libllvm21 >=21.1.7,<21.2.0a0
+ - libstdcxx >=14
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
+ purls: []
+ size: 12117823
+ timestamp: 1767060743508
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-hb8b1518_5.conda
+ sha256: cb83980c57e311783ee831832eb2c20ecb41e7dee6e86e8b70b8cef0e43eab55
+ md5: d4a250da4737ee127fb1fa6452a9002e
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=13
+ - libstdcxx >=13
+ - libzlib >=1.3.1,<2.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 4523621
+ timestamp: 1749905341688
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h5cdc715_5.conda
+ sha256: f3282d27be35e5d29b5b798e5136427ec798916ee6374499be7b7682c8582b72
+ md5: ac0333d338076ef19170938bbaf97582
+ depends:
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=13
+ - libstdcxx >=13
+ - libzlib >=1.3.1,<2.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 4550533
+ timestamp: 1749906839681
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.17.0-h4e3cde8_1.conda
+ sha256: 2d7be2fe0f58a0945692abee7bb909f8b19284b518d958747e5ff51d0655c303
+ md5: 117499f93e892ea1e57fdca16c2e8351
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=14
+ - libnghttp2 >=1.67.0,<2.0a0
+ - libssh2 >=1.11.1,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: curl
+ license_family: MIT
+ purls: []
+ size: 459417
+ timestamp: 1765379027010
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.17.0-h7bfdcfb_1.conda
+ sha256: 1976e96cb86f1e9f0993cbba7a0b482e5f5dc9c3a0be23870b70125c95d96ddb
+ md5: 3b71a8bb2b714aa8d0a34c9a90e0eec2
+ depends:
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=14
+ - libnghttp2 >=1.67.0,<2.0a0
+ - libssh2 >=1.11.1,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: curl
+ license_family: MIT
+ purls: []
+ size: 479017
+ timestamp: 1765378979432
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.17.0-hdece5d2_1.conda
+ sha256: 1a8a958448610ca3f8facddfe261fdbb010e7029a1571b84052ec9770fc0a36e
+ md5: 1d6e791c6e264ae139d469ce011aab51
+ depends:
+ - __osx >=11.0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libnghttp2 >=1.67.0,<2.0a0
+ - libssh2 >=1.11.1,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: curl
+ license_family: MIT
+ purls: []
+ size: 394471
+ timestamp: 1765379821294
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-21.1.8-hf598326_0.conda
+ sha256: 82e228975fd491bcf1071ecd0a6ec2a0fcc5f57eb0bd1d52cb13a18d57c67786
+ md5: 780f0251b757564e062187044232c2b7
+ depends:
+ - __osx >=11.0
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
+ purls: []
+ size: 569118
+ timestamp: 1765919724254
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda
+ sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680
+ md5: 6c77a605a7a689d17d4819c0f8ac9a00
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 73490
+ timestamp: 1761979956660
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda
+ sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392
+ md5: a9138815598fe6b91a1d6782ca657b0c
+ depends:
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 71117
+ timestamp: 1761979776756
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libdeflate-1.25-hc11a715_0.conda
+ sha256: 5e0b6961be3304a5f027a8c00bd0967fc46ae162cffb7553ff45c70f51b8314c
+ md5: a6130c709305cd9828b4e1bd9ba0000c
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 55420
+ timestamp: 1761980066242
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libdrm-2.4.125-hb03c661_1.conda
+ sha256: c076a213bd3676cc1ef22eeff91588826273513ccc6040d9bea68bccdc849501
+ md5: 9314bc5a1fe7d1044dc9dfd3ef400535
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libpciaccess >=0.18,<0.19.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 310785
+ timestamp: 1757212153962
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdrm-2.4.125-he30d5cf_1.conda
+ sha256: 4e6cdb5dd37db794b88bec714b4418a0435b04d14e9f7afc8cc32f2a3ced12f2
+ md5: 2079727b538f6dd16f3fa579d4c3c53f
+ depends:
+ - libgcc >=14
+ - libpciaccess >=0.18,<0.19.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 344548
+ timestamp: 1757212128414
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda
+ sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724
+ md5: c277e0a4d549b03ac1e9d6cbbe3d017b
+ depends:
+ - ncurses
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - ncurses >=6.5,<7.0a0
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 134676
+ timestamp: 1738479519902
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda
+ sha256: c0b27546aa3a23d47919226b3a1635fccdb4f24b94e72e206a751b33f46fd8d6
+ md5: fb640d776fc92b682a14e001980825b1
+ depends:
+ - ncurses
+ - libgcc >=13
+ - ncurses >=6.5,<7.0a0
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 148125
+ timestamp: 1738479808948
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda
+ sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631
+ md5: 44083d2d2c2025afca315c7a172eab2b
+ depends:
+ - ncurses
+ - __osx >=11.0
+ - ncurses >=6.5,<7.0a0
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 107691
+ timestamp: 1738479560845
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libegl-1.7.0-ha4b6fd6_2.conda
+ sha256: 7fd5408d359d05a969133e47af580183fbf38e2235b562193d427bb9dad79723
+ md5: c151d5eb730e9b7480e6d48c0fc44048
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libglvnd 1.7.0 ha4b6fd6_2
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 44840
+ timestamp: 1731330973553
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libegl-1.7.0-hd24410f_2.conda
+ sha256: 8962abf38a58c235611ce356b9899f6caeb0352a8bce631b0bcc59352fda455e
+ md5: cf105bce884e4ef8c8ccdca9fe6695e7
+ depends:
+ - libglvnd 1.7.0 hd24410f_2
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 53551
+ timestamp: 1731330990477
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda
+ sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4
+ md5: 172bf1cd1ff8629f2b1179945ed45055
+ depends:
+ - libgcc-ng >=12
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 112766
+ timestamp: 1702146165126
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda
+ sha256: 973af77e297f1955dd1f69c2cbdc5ab9dfc88388a5576cd152cda178af0fd006
+ md5: a9a13cb143bbaa477b1ebaefbe47a302
+ depends:
+ - libgcc-ng >=12
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 115123
+ timestamp: 1702146237623
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda
+ sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f
+ md5: 36d33e440c31857372a72137f78bacf5
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 107458
+ timestamp: 1702146414478
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda
+ sha256: 1e1b08f6211629cbc2efe7a5bca5953f8f6b3cae0eeb04ca4dacee1bd4e2db2f
+ md5: 8b09ae86839581147ef2e5c5e229d164
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ constrains:
+ - expat 2.7.3.*
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 76643
+ timestamp: 1763549731408
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.3-hfae3067_0.conda
+ sha256: cc2581a78315418cc2e0bb2a273d37363203e79cefe78ba6d282fed546262239
+ md5: b414e36fbb7ca122030276c75fa9c34a
+ depends:
+ - libgcc >=14
+ constrains:
+ - expat 2.7.3.*
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 76201
+ timestamp: 1763549910086
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda
+ sha256: fce22610ecc95e6d149e42a42fbc3cc9d9179bd4eb6232639a60f06e080eec98
+ md5: b79875dbb5b1db9a4a22a4520f918e1a
+ depends:
+ - __osx >=11.0
+ constrains:
+ - expat 2.7.3.*
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 67800
+ timestamp: 1763549994166
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda
+ sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54
+ md5: 35f29eec58405aaf55e01cb470d8c26a
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 57821
+ timestamp: 1760295480630
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-hd65408f_0.conda
+ sha256: 6c3332e78a975e092e54f87771611db81dcb5515a3847a3641021621de76caea
+ md5: 0c5ad486dcfb188885e3cf8ba209b97b
+ depends:
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 55586
+ timestamp: 1760295405021
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda
+ sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f
+ md5: 411ff7cd5d1472bba0f55c0faf04453b
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 40251
+ timestamp: 1760295839166
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda
+ sha256: 4641d37faeb97cf8a121efafd6afd040904d4bca8c46798122f417c31d5dfbec
+ md5: f4084e4e6577797150f9b04a4560ceb0
+ depends:
+ - libfreetype6 >=2.14.1
+ license: GPL-2.0-only OR FTL
+ purls: []
+ size: 7664
+ timestamp: 1757945417134
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.1-h8af1aa0_0.conda
+ sha256: 342c07e4be3d09d04b531c889182a11a488e7e9ba4b75f642040e4681c1e9b98
+ md5: 1e61fb236ccd3d6ccaf9e91cb2d7e12d
+ depends:
+ - libfreetype6 >=2.14.1
+ license: GPL-2.0-only OR FTL
+ purls: []
+ size: 7753
+ timestamp: 1757945484817
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda
+ sha256: 9de25a86066f078822d8dd95a83048d7dc2897d5d655c0e04a8a54fca13ef1ef
+ md5: f35fb38e89e2776994131fbf961fa44b
+ depends:
+ - libfreetype6 >=2.14.1
+ license: GPL-2.0-only OR FTL
+ purls: []
+ size: 7810
+ timestamp: 1757947168537
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.1-h73754d4_0.conda
+ sha256: 4a7af818a3179fafb6c91111752954e29d3a2a950259c14a2fc7ba40a8b03652
+ md5: 8e7251989bca326a28f4a5ffbd74557a
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libpng >=1.6.50,<1.7.0a0
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - freetype >=2.14.1
+ license: GPL-2.0-only OR FTL
+ purls: []
+ size: 386739
+ timestamp: 1757945416744
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.1-hdae7a39_0.conda
+ sha256: cedc83d9733363aca353872c3bfed2e188aa7caf57b57842ba0c6d2765652b7c
+ md5: 9c2f56b6e011c6d8010ff43b796aab2f
+ depends:
+ - libgcc >=14
+ - libpng >=1.6.50,<1.7.0a0
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - freetype >=2.14.1
+ license: GPL-2.0-only OR FTL
+ purls: []
+ size: 423210
+ timestamp: 1757945484108
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda
+ sha256: cc4aec4c490123c0f248c1acd1aeab592afb6a44b1536734e20937cda748f7cd
+ md5: 6d4ede03e2a8e20eb51f7f681d2a2550
+ depends:
+ - __osx >=11.0
+ - libpng >=1.6.50,<1.7.0a0
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - freetype >=2.14.1
+ license: GPL-2.0-only OR FTL
+ purls: []
+ size: 346703
+ timestamp: 1757947166116
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_16.conda
+ sha256: 6eed58051c2e12b804d53ceff5994a350c61baf117ec83f5f10c953a3f311451
+ md5: 6d0363467e6ed84f11435eb309f2ff06
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _openmp_mutex >=4.5
+ constrains:
+ - libgcc-ng ==15.2.0=*_16
+ - libgomp 15.2.0 he0feb66_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 1042798
+ timestamp: 1765256792743
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_16.conda
+ sha256: 44bfc6fe16236babb271e0c693fe7fd978f336542e23c9c30e700483796ed30b
+ md5: cf9cd6739a3b694dcf551d898e112331
+ depends:
+ - _openmp_mutex >=4.5
+ constrains:
+ - libgomp 15.2.0 h8acb6b2_16
+ - libgcc-ng ==15.2.0=*_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 620637
+ timestamp: 1765256938043
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_16.conda
+ sha256: 646c91dbc422fe92a5f8a3a5409c9aac66549f4ce8f8d1cab7c2aa5db789bb69
+ md5: 8b216bac0de7a9d60f3ddeba2515545c
+ depends:
+ - _openmp_mutex
+ constrains:
+ - libgcc-ng ==15.2.0=*_16
+ - libgomp 15.2.0 16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 402197
+ timestamp: 1765258985740
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_16.conda
+ sha256: 5f07f9317f596a201cc6e095e5fc92621afca64829785e483738d935f8cab361
+ md5: 5a68259fac2da8f2ee6f7bfe49c9eb8b
+ depends:
+ - libgcc 15.2.0 he0feb66_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 27256
+ timestamp: 1765256804124
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_16.conda
+ sha256: 22d7e63a00c880bd14fbbc514ec6f553b9325d705f08582e9076c7e73c93a2e1
+ md5: 3e54a6d0f2ff0172903c0acfda9efc0e
+ depends:
+ - libgcc 15.2.0 h8acb6b2_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 27356
+ timestamp: 1765256948637
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_16.conda
+ sha256: 8a7b01e1ee1c462ad243524d76099e7174ebdd94ff045fe3e9b1e58db196463b
+ md5: 40d9b534410403c821ff64f00d0adc22
+ depends:
+ - libgfortran5 15.2.0 h68bc16d_16
+ constrains:
+ - libgfortran-ng ==15.2.0=*_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 27215
+ timestamp: 1765256845586
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_16.conda
+ sha256: 02fa489a333ee4bb5483ae6bf221386b67c25d318f2f856237821a7c9333d5be
+ md5: 776cca322459d09aad229a49761c0654
+ depends:
+ - libgfortran5 15.2.0 h1b7bec0_16
+ constrains:
+ - libgfortran-ng ==15.2.0=*_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 27314
+ timestamp: 1765256989755
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_16.conda
+ sha256: 68a6c1384d209f8654112c4c57c68c540540dd8e09e17dd1facf6cf3467798b5
+ md5: 11e09edf0dde4c288508501fe621bab4
+ depends:
+ - libgfortran5 15.2.0 hdae7583_16
+ constrains:
+ - libgfortran-ng ==15.2.0=*_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 138630
+ timestamp: 1765259217400
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_16.conda
+ sha256: d0e974ebc937c67ae37f07a28edace978e01dc0f44ee02f29ab8a16004b8148b
+ md5: 39183d4e0c05609fd65f130633194e37
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=15.2.0
+ constrains:
+ - libgfortran 15.2.0
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 2480559
+ timestamp: 1765256819588
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_16.conda
+ sha256: bde541944566254147aab746e66014682e37a259c9a57a0516cf5d05ec343d14
+ md5: 87b4ffedaba8b4d675479313af74f612
+ depends:
+ - libgcc >=15.2.0
+ constrains:
+ - libgfortran 15.2.0
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 1485817
+ timestamp: 1765256963205
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_16.conda
+ sha256: 9fb7f4ff219e3fb5decbd0ee90a950f4078c90a86f5d8d61ca608c913062f9b0
+ md5: 265a9d03461da24884ecc8eb58396d57
+ depends:
+ - libgcc >=15.2.0
+ constrains:
+ - libgfortran 15.2.0
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 598291
+ timestamp: 1765258993165
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgl-1.7.0-ha4b6fd6_2.conda
+ sha256: dc2752241fa3d9e40ce552c1942d0a4b5eeb93740c9723873f6fcf8d39ef8d2d
+ md5: 928b8be80851f5d8ffb016f9c81dae7a
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libglvnd 1.7.0 ha4b6fd6_2
+ - libglx 1.7.0 ha4b6fd6_2
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 134712
+ timestamp: 1731330998354
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgl-1.7.0-hd24410f_2.conda
+ sha256: 3e954380f16255d1c8ae5da3bd3044d3576a0e1ac2e3c3ff2fe8f2f1ad2e467a
+ md5: 0d00176464ebb25af83d40736a2cd3bb
+ depends:
+ - libglvnd 1.7.0 hd24410f_2
+ - libglx 1.7.0 hd24410f_2
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 145442
+ timestamp: 1731331005019
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.3-h6548e54_0.conda
+ sha256: 82d6c2ee9f548c84220fb30fb1b231c64a53561d6e485447394f0a0eeeffe0e6
+ md5: 034bea55a4feef51c98e8449938e9cee
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - libiconv >=1.18,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - pcre2 >=10.47,<10.48.0a0
+ constrains:
+ - glib 2.86.3 *_0
+ license: LGPL-2.1-or-later
+ purls: []
+ size: 3946542
+ timestamp: 1765221858705
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.3-hf53f6bf_0.conda
+ sha256: 35f4262131e4d42514787fdc3d45c836e060e18fcb2441abd9dd8ecd386214f4
+ md5: f226b9798c6c176d2a94eea1350b3b6b
+ depends:
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - libiconv >=1.18,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - pcre2 >=10.47,<10.48.0a0
+ constrains:
+ - glib 2.86.3 *_0
+ license: LGPL-2.1-or-later
+ purls: []
+ size: 4041779
+ timestamp: 1765221790843
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libglvnd-1.7.0-ha4b6fd6_2.conda
+ sha256: 1175f8a7a0c68b7f81962699751bb6574e6f07db4c9f72825f978e3016f46850
+ md5: 434ca7e50e40f4918ab701e3facd59a0
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 132463
+ timestamp: 1731330968309
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglvnd-1.7.0-hd24410f_2.conda
+ sha256: 57ec3898a923d4bcc064669e90e8abfc4d1d945a13639470ba5f3748bd3090da
+ md5: 9e115653741810778c9a915a2f8439e7
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 152135
+ timestamp: 1731330986070
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libglx-1.7.0-ha4b6fd6_2.conda
+ sha256: 2d35a679624a93ce5b3e9dd301fff92343db609b79f0363e6d0ceb3a6478bfa7
+ md5: c8013e438185f33b13814c5c488acd5c
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libglvnd 1.7.0 ha4b6fd6_2
+ - xorg-libx11 >=1.8.10,<2.0a0
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 75504
+ timestamp: 1731330988898
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglx-1.7.0-hd24410f_2.conda
+ sha256: 6591af640cb05a399fab47646025f8b1e1a06a0d4bbb4d2e320d6629b47a1c61
+ md5: 1d4269e233636148696a67e2d30dad2a
+ depends:
+ - libglvnd 1.7.0 hd24410f_2
+ - xorg-libx11 >=1.8.9,<2.0a0
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 77736
+ timestamp: 1731330998960
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_16.conda
+ sha256: 5b3e5e4e9270ecfcd48f47e3a68f037f5ab0f529ccb223e8e5d5ac75a58fc687
+ md5: 26c46f90d0e727e95c6c9498a33a09f3
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 603284
+ timestamp: 1765256703881
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_16.conda
+ sha256: 0a9d77c920db691eb42b78c734d70c5a1d00b3110c0867cfff18e9dd69bc3c29
+ md5: 4d2f224e8186e7881d53e3aead912f6c
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 587924
+ timestamp: 1765256821307
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.73.1-h3288cfb_1.conda
+ sha256: bc9d32af6167b1f5bcda216dc44eddcb27f3492440571ab12f6e577472a05e34
+ md5: ff63bb12ac31c176ff257e3289f20770
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - c-ares >=1.34.5,<2.0a0
+ - libabseil * cxx17*
+ - libabseil >=20250512.1,<20250513.0a0
+ - libgcc >=14
+ - libprotobuf >=6.31.1,<6.31.2.0a0
+ - libre2-11 >=2025.8.12
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - re2
+ constrains:
+ - grpc-cpp =1.73.1
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 8349777
+ timestamp: 1761058442526
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgrpc-1.67.1-hf7ccdd3_2.conda
+ sha256: 066961d846f760770b1f5b7c8a0a322c5de04a8efb4b2850d10aa82b7abb3a88
+ md5: ccc6301f028063362fdc95a4582d0eaa
+ depends:
+ - c-ares >=1.34.4,<2.0a0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libgcc >=13
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libre2-11 >=2024.7.2
+ - libstdcxx >=13
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.4.1,<4.0a0
+ - re2
+ constrains:
+ - grpc-cpp =1.67.1
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 7080890
+ timestamp: 1740786546915
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.67.1-h0a426d6_2.conda
+ sha256: a6114f6020f02387aa8bc9167d77c23177f8a3650b55fb0ee100c5227ca475f9
+ md5: c368d17cdc54d96aa6bd73d07816cf60
+ depends:
+ - __osx >=11.0
+ - c-ares >=1.34.4,<2.0a0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcxx >=18
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libre2-11 >=2024.7.2
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.4.1,<4.0a0
+ - re2
+ constrains:
+ - grpc-cpp =1.67.1
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 5203869
+ timestamp: 1740786448002
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda
+ sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f
+ md5: 915f5995e94f60e9a4826e0b0920ee88
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: LGPL-2.1-only
+ purls: []
+ size: 790176
+ timestamp: 1754908768807
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda
+ sha256: 1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9
+ md5: 5a86bf847b9b926f3a4f203339748d78
+ depends:
+ - libgcc >=14
+ license: LGPL-2.1-only
+ purls: []
+ size: 791226
+ timestamp: 1754910975665
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda
+ sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32
+ md5: 8397539e3a0bbd1695584fb4f927485a
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ constrains:
+ - jpeg <0.0.0a
+ license: IJG AND BSD-3-Clause AND Zlib
+ purls: []
+ size: 633710
+ timestamp: 1762094827865
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda
+ sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6
+ md5: 5109d7f837a3dfdf5c60f60e311b041f
+ depends:
+ - libgcc >=14
+ constrains:
+ - jpeg <0.0.0a
+ license: IJG AND BSD-3-Clause AND Zlib
+ purls: []
+ size: 691818
+ timestamp: 1762094728337
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libjpeg-turbo-3.1.2-hc919400_0.conda
+ sha256: 6c061c56058bb10374daaef50e81b39cf43e8aee21f0037022c0c39c4f31872f
+ md5: f0695fbecf1006f27f4395d64bd0c4b8
+ depends:
+ - __osx >=11.0
+ constrains:
+ - jpeg <0.0.0a
+ license: IJG AND BSD-3-Clause AND Zlib
+ purls: []
+ size: 551197
+ timestamp: 1762095054358
+- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda
+ build_number: 5
+ sha256: c723b6599fcd4c6c75dee728359ef418307280fa3e2ee376e14e85e5bbdda053
+ md5: b38076eb5c8e40d0106beda6f95d7609
+ depends:
+ - libblas 3.11.0 5_h4a7cf45_openblas
+ constrains:
+ - blas 2.305 openblas
+ - liblapacke 3.11.0 5*_openblas
+ - libcblas 3.11.0 5*_openblas
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18200
+ timestamp: 1765818857876
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda
+ build_number: 5
+ sha256: 692222d186d3ffbc99eaf04b5b20181fd26aee1edec1106435a0a755c57cce86
+ md5: 88d1e4133d1182522b403e9ba7435f04
+ depends:
+ - libblas 3.11.0 5_haddc8a3_openblas
+ constrains:
+ - liblapacke 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ - libcblas 3.11.0 5*_openblas
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18392
+ timestamp: 1765818627104
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda
+ build_number: 5
+ sha256: 735a6e6f7d7da6f718b6690b7c0a8ae4815afb89138aa5793abe78128e951dbb
+ md5: ca9d752201b7fa1225bca036ee300f2b
+ depends:
+ - libblas 3.11.0 5_h51639a9_openblas
+ constrains:
+ - libcblas 3.11.0 5*_openblas
+ - blas 2.305 openblas
+ - liblapacke 3.11.0 5*_openblas
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 18551
+ timestamp: 1765819121855
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda
+ sha256: 91bb4f5be1601b40b4995911d785e29387970f0b3c80f33f7f9028f95335399f
+ md5: 1a2708a460884d6861425b7f9a7bef99
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - libzlib >=1.3.1,<2.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
+ purls: []
+ size: 44333366
+ timestamp: 1765959132513
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm21-21.1.8-hfd2ba90_0.conda
+ sha256: 5af18365698a9093a81490de16c97a0af5318e20086b74998718f1e5d7566e74
+ md5: de59c5148c2a8347c02e437e3ed242a0
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - libzlib >=1.3.1,<2.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
+ purls: []
+ size: 43148553
+ timestamp: 1765930975162
+- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda
+ sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8
+ md5: 1a580f7796c7bf6393fddb8bbbde58dc
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ constrains:
+ - xz 5.8.1.*
+ license: 0BSD
+ purls: []
+ size: 112894
+ timestamp: 1749230047870
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.1-h86ecc28_2.conda
+ sha256: 498ea4b29155df69d7f20990a7028d75d91dbea24d04b2eb8a3d6ef328806849
+ md5: 7d362346a479256857ab338588190da0
+ depends:
+ - libgcc >=13
+ constrains:
+ - xz 5.8.1.*
+ license: 0BSD
+ purls: []
+ size: 125103
+ timestamp: 1749232230009
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda
+ sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285
+ md5: d6df911d4564d77c4374b02552cb17d1
+ depends:
+ - __osx >=11.0
+ constrains:
+ - xz 5.8.1.*
+ license: 0BSD
+ purls: []
+ size: 92286
+ timestamp: 1749230283517
+- conda: https://conda.anaconda.org/conda-forge/noarch/libml_dtypes-headers-0.5.4-h707e725_0.conda
+ sha256: 37e3fe66ec86b8fff9db741a1e6fcc19874646702aaa74c97bf26852ffbd0276
+ md5: 597a39bc0946262b29644366059cd109
+ depends:
+ - __unix
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 23946
+ timestamp: 1764082185215
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda
+ sha256: a4a7dab8db4dc81c736e9a9b42bdfd97b087816e029e221380511960ac46c690
+ md5: b499ce4b026493a13774bcf0f4c33849
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - c-ares >=1.34.5,<2.0a0
+ - libev >=4.33,<4.34.0a0
+ - libev >=4.33,<5.0a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.2,<4.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 666600
+ timestamp: 1756834976695
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.67.0-ha888d0e_0.conda
+ sha256: b03f406fd5c3f865a5e08c89b625245a9c4e026438fd1a445e45e6a0d69c2749
+ md5: 981082c1cc262f514a5a2cf37cab9b81
+ depends:
+ - c-ares >=1.34.5,<2.0a0
+ - libev >=4.33,<4.34.0a0
+ - libev >=4.33,<5.0a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.2,<4.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 728661
+ timestamp: 1756835019535
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda
+ sha256: a07cb53b5ffa2d5a18afc6fd5a526a5a53dd9523fbc022148bd2f9395697c46d
+ md5: a4b4dd73c67df470d091312ab87bf6ae
+ depends:
+ - __osx >=11.0
+ - c-ares >=1.34.5,<2.0a0
+ - libcxx >=19
+ - libev >=4.33,<4.34.0a0
+ - libev >=4.33,<5.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.2,<4.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 575454
+ timestamp: 1756835746393
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda
+ sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5
+ md5: d864d34357c3b65a4b731f78c0801dc4
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ license: LGPL-2.1-only
+ license_family: GPL
+ purls: []
+ size: 33731
+ timestamp: 1750274110928
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda
+ sha256: c0dc4d84198e3eef1f37321299e48e2754ca83fd12e6284754e3cb231357c3a5
+ md5: d5d58b2dc3e57073fe22303f5fed4db7
+ depends:
+ - libgcc >=13
+ license: LGPL-2.1-only
+ license_family: GPL
+ purls: []
+ size: 34831
+ timestamp: 1750274211
+- 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: []
+ size: 33418
+ timestamp: 1734670021371
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libntlm-1.4-hf897c2e_1002.tar.bz2
+ sha256: 0e303d7a8845391bd1634efb65dc9d9b82b5608ebeb32fb77a56d1ed696d2eee
+ md5: 835c7c4137821de5c309f4266a51ba89
+ depends:
+ - libgcc-ng >=9.3.0
+ license: LGPL-2.1-or-later
+ purls: []
+ size: 39449
+ timestamp: 1609781865660
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda
+ sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5
+ md5: be43915efc66345cccb3c310b6ed0374
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libgfortran
+ - libgfortran5 >=14.3.0
+ constrains:
+ - openblas >=0.3.30,<0.3.31.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 5927939
+ timestamp: 1763114673331
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda
+ sha256: 794a7270ea049ec931537874cd8d2de0ef4b3cef71c055cfd8b4be6d2f4228b0
+ md5: 11d7d57b7bdd01da745bbf2b67020b2e
+ depends:
+ - libgcc >=14
+ - libgfortran
+ - libgfortran5 >=14.3.0
+ constrains:
+ - openblas >=0.3.30,<0.3.31.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 4959359
+ timestamp: 1763114173544
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_3.conda
+ sha256: dcc626c7103503d1dfc0371687ad553cb948b8ed0249c2a721147bdeb8db4a73
+ md5: a18a7f471c517062ee71b843ef95eb8a
+ depends:
+ - __osx >=11.0
+ - libgfortran
+ - libgfortran5 >=14.3.0
+ - llvm-openmp >=19.1.7
+ constrains:
+ - openblas >=0.3.30,<0.3.31.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 4285762
+ timestamp: 1761749506256
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda
+ sha256: 215086c108d80349e96051ad14131b751d17af3ed2cb5a34edd62fa89bfe8ead
+ md5: 7df50d44d4a14d6c31a2c54f2cd92157
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libglvnd 1.7.0 ha4b6fd6_2
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 50757
+ timestamp: 1731330993524
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopengl-1.7.0-hd24410f_2.conda
+ sha256: e359df399fb2f308774237384414e318fac8870c1bf6481bdc67ae16e0bd2a02
+ md5: cf9d12bfab305e48d095a4c79002c922
+ depends:
+ - libglvnd 1.7.0 hd24410f_2
+ license: LicenseRef-libglvnd
+ purls: []
+ size: 56355
+ timestamp: 1731331001820
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda
+ sha256: 0bd91de9b447a2991e666f284ae8c722ffb1d84acb594dbd0c031bd656fa32b2
+ md5: 70e3400cbbfa03e96dcde7fc13e38c7b
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 28424
+ timestamp: 1749901812541
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpciaccess-0.18-h86ecc28_0.conda
+ sha256: 7641dfdfe9bda7069ae94379e9924892f0b6604c1a016a3f76b230433bb280f2
+ md5: 5044e160c5306968d956c2a0a2a440d6
+ depends:
+ - libgcc >=13
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 29512
+ timestamp: 1749901899881
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.53-h421ea60_0.conda
+ sha256: 8acdeb9a7e3d2630176ba8e947caf6bf4985a5148dec69b801e5eb797856688b
+ md5: 00d4e66b1f746cb14944cad23fffb405
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: zlib-acknowledgement
+ purls: []
+ size: 317748
+ timestamp: 1764981060755
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.53-h1abf092_0.conda
+ sha256: 31c2b22aa4cb2b8d1456ad5aa92d1b95a8db234572cd29772c58e0b0c5be8823
+ md5: 7591d867dbcba9eb7fb5e88a5f756591
+ depends:
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: zlib-acknowledgement
+ purls: []
+ size: 340043
+ timestamp: 1764981067899
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libpng-1.6.53-hfab5511_0.conda
+ sha256: 6793e7284e175c515fc6453be45c7c0febdea853657d246d8136fbda791dd0ad
+ md5: 62b6111feeffe607c3ecc8ca5bd1514b
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.1,<2.0a0
+ license: zlib-acknowledgement
+ purls: []
+ size: 288210
+ timestamp: 1764981075326
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libpq-18.1-h5c52fec_2.conda
+ sha256: bbab2c3e6f650f2bd1bc84d88e6a20fefa6a401fa445bb4b97c509c1b3a89fa8
+ md5: a8ac9a6342569d1714ae1b53ae2fcadb
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - icu >=75.1,<76.0a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=14
+ - openldap >=2.6.10,<2.7.0a0
+ - openssl >=3.5.4,<4.0a0
+ license: PostgreSQL
+ purls: []
+ size: 2711480
+ timestamp: 1764345810429
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpq-18.1-haf03d9f_2.conda
+ sha256: 14f7609f8074bd689fafa981c3bbf07ee2a37f5d7f40e158d01a25fe280e2177
+ md5: 8b0d66c4db91b3ef64daad7f61a569d0
+ depends:
+ - icu >=75.1,<76.0a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=14
+ - openldap >=2.6.10,<2.7.0a0
+ - openssl >=3.5.4,<4.0a0
+ license: PostgreSQL
+ purls: []
+ size: 2783759
+ timestamp: 1764345873700
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-6.31.1-h49aed37_4.conda
+ sha256: 0ef142ac31e6fd59b4af89ac800acb6deb3fbd9cc4ccf070c03cc2c784dc7296
+ md5: 07479fc04ba3ddd5d9f760ef1635cfa7
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libabseil * cxx17*
+ - libabseil >=20250512.1,<20250513.0a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 4372578
+ timestamp: 1766316228461
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-5.28.3-h44a3b7b_1.conda
+ sha256: ecb69f2b1668e784b41ba667493be846662d5ef702bef64fb2e013bb1364cdc4
+ md5: 68f807f7cc13951652bbe048253fd405
+ depends:
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libgcc >=13
+ - libstdcxx >=13
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 2788074
+ timestamp: 1735576315676
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-5.28.3-h3bd63a1_1.conda
+ sha256: f58a16b13ad53346903c833e266f83c3d770a43a432659b98710aed85ca885e7
+ md5: bdbfea4cf45ae36652c6bbcc2e7ebe91
+ depends:
+ - __osx >=11.0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcxx >=18
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 2271580
+ timestamp: 1735576361997
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libre2-11-2025.11.05-h7b12aa8_0.conda
+ sha256: eb5d5ef4d12cdf744e0f728b35bca910843c8cf1249f758cf15488ca04a21dbb
+ md5: a30848ebf39327ea078cf26d114cff53
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libabseil * cxx17*
+ - libabseil >=20250512.1,<20250513.0a0
+ - libgcc >=14
+ - libstdcxx >=14
+ constrains:
+ - re2 2025.11.05.*
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 211099
+ timestamp: 1762397758105
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2024.07.02-h18dbdb1_2.conda
+ sha256: 862c20de0120f802e618dcb25913d00c5b82f91f4be60b2d46a774e851adc2f6
+ md5: 9a7dbbaab49f76a6f36e5c9d98e323a7
+ depends:
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libgcc >=13
+ - libstdcxx >=13
+ constrains:
+ - re2 2024.07.02.*
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 204305
+ timestamp: 1735540986919
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2024.07.02-h07bc746_2.conda
+ sha256: 112a73ad483353751d4c5d63648c69a4d6fcebf5e1b698a860a3f5124fc3db96
+ md5: 6b1e3624d3488016ca4f1ca0c412efaa
+ depends:
+ - __osx >=11.0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcxx >=18
+ constrains:
+ - re2 2024.07.02.*
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 167155
+ timestamp: 1735541067807
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.51.1-h0c1763c_1.conda
+ sha256: 5ef162b2a1390d1495a759734afe2312a358a58441cf8f378be651903646f3b7
+ md5: ad1fd565aff83b543d726382c0ab0af2
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: blessing
+ purls: []
+ size: 940686
+ timestamp: 1766319628770
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.51.1-h022381a_1.conda
+ sha256: 305549275aed7ef3e9467fe2ae81fc3aa3f1b959356be8290b930e20ebf9e306
+ md5: e58189dfb17dd3f871427bd2fe8dd99b
+ depends:
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: blessing
+ purls: []
+ size: 938993
+ timestamp: 1766319571604
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.51.1-h1b79a29_1.conda
+ sha256: f2c3cbf2ca7d697098964a748fbf19d6e4adcefa23844ec49f0166f1d36af83c
+ md5: 8c3951797658e10b610929c3e57e9ad9
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.1,<2.0a0
+ license: blessing
+ purls: []
+ size: 905861
+ timestamp: 1766319901587
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda
+ sha256: fa39bfd69228a13e553bd24601332b7cfeb30ca11a3ca50bb028108fe90a7661
+ md5: eecce068c7e4eddeb169591baac20ac4
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.0,<4.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 304790
+ timestamp: 1745608545575
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda
+ sha256: 1e289bcce4ee6a5817a19c66e296f3c644dcfa6e562e5c1cba807270798814e7
+ md5: eecc495bcfdd9da8058969656f916cc2
+ depends:
+ - libgcc >=13
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.0,<4.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 311396
+ timestamp: 1745609845915
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda
+ sha256: 8bfe837221390ffc6f111ecca24fa12d4a6325da0c8d131333d63d6c37f27e0a
+ md5: b68e8f66b94b44aaa8de4583d3d4cc40
+ depends:
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.0,<4.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 279193
+ timestamp: 1745608793272
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_16.conda
+ sha256: 813427918316a00c904723f1dfc3da1bbc1974c5cfe1ed1e704c6f4e0798cbc6
+ md5: 68f68355000ec3f1d6f26ea13e8f525f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc 15.2.0 he0feb66_16
+ constrains:
+ - libstdcxx-ng ==15.2.0=*_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 5856456
+ timestamp: 1765256838573
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_16.conda
+ sha256: 4db11a903707068ae37aa6909511c68e9af6a2e97890d1b73b0a8d87cb74aba9
+ md5: 52d9df8055af3f1665ba471cce77da48
+ depends:
+ - libgcc 15.2.0 h8acb6b2_16
+ constrains:
+ - libstdcxx-ng ==15.2.0=*_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 5541149
+ timestamp: 1765256980783
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_16.conda
+ sha256: 81f2f246c7533b41c5e0c274172d607829019621c4a0823b5c0b4a8c7028ee84
+ md5: 1b3152694d236cf233b76b8c56bf0eae
+ depends:
+ - libstdcxx 15.2.0 h934c35e_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 27300
+ timestamp: 1765256885128
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_16.conda
+ sha256: dd5c813ae5a4dac6fa946352674e0c21b1847994a717ef67bd6cc77bc15920be
+ md5: 20b7f96f58ccbe8931c3a20778fb3b32
+ depends:
+ - libstdcxx 15.2.0 hef695bb_16
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ purls: []
+ size: 27376
+ timestamp: 1765257033344
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libtensorflow_cc-2.19.1-cpu_hf7abd0a_2.conda
+ sha256: 5b13b874a6f2e75373992f936fae2c87c51a0531136d402be93d0e0c7a8ca49a
+ md5: 5b5911b4fab716ec45704f84f611d557
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _x86_64-microarch-level >=1
+ - flatbuffers >=25.2.10,<25.2.11.0a0
+ - giflib >=5.2.2,<5.3.0a0
+ - icu >=75.1,<76.0a0
+ - libabseil * cxx17*
+ - libabseil >=20250512.1,<20250513.0a0
+ - libcurl >=8.17.0,<9.0a0
+ - libgcc >=14
+ - libgrpc >=1.73.1,<1.74.0a0
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - libml_dtypes-headers >=0.5.1,<0.6
+ - libpng >=1.6.51,<1.7.0a0
+ - libprotobuf >=6.31.1,<6.31.2.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libstdcxx >=14
+ - libtensorflow_framework 2.19.1 cpu_h12ecb4a_2
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - snappy >=1.2.2,<1.3.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 145175442
+ timestamp: 1764396561544
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtensorflow_cc-2.18.0-cpu_h26186cf_2.conda
+ sha256: 2ac0e04aed02b5ebe6eed194f6c24ee5ecfa47b4accead534c921ad9b1924f18
+ md5: fe3d607b65d3627797c8488ab6d0bf74
+ depends:
+ - flatbuffers >=24.12.23,<24.12.24.0a0
+ - giflib >=5.2.2,<5.3.0a0
+ - icu >=75.1,<76.0a0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcurl >=8.14.1,<9.0a0
+ - libgcc
+ - libgcc-ng >=12
+ - libgrpc >=1.67.1,<1.68.0a0
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - libml_dtypes-headers >=0.5.0,<0.6
+ - libpng >=1.6.50,<1.7.0a0
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libstdcxx
+ - libstdcxx-ng >=12
+ - libtensorflow_framework 2.18.0 cpu_h78d15be_2
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.2,<4.0a0
+ - snappy >=1.2.2,<1.3.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 126963221
+ timestamp: 1757538219396
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtensorflow_cc-2.18.0-cpu_hf321e49_1.conda
+ sha256: 6b96f28b9ac3c0224bbb3bfa20b214728d698774293c85253280bda3e314c6e5
+ md5: 282c90a2f61920045a68a2c336af3c51
+ depends:
+ - __osx >=11.0
+ - flatbuffers >=24.12.23,<24.12.24.0a0
+ - giflib >=5.2.2,<5.3.0a0
+ - icu >=75.1,<76.0a0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcurl >=8.14.1,<9.0a0
+ - libcxx >=18
+ - libgrpc >=1.67.1,<1.68.0a0
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - libml_dtypes-headers >=0.5.0,<0.6
+ - libpng >=1.6.50,<1.7.0a0
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libtensorflow_framework 2.18.0 cpu_h2398287_1
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.2,<4.0a0
+ - snappy >=1.2.2,<1.3.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 120088427
+ timestamp: 1754497895714
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libtensorflow_framework-2.19.1-cpu_h12ecb4a_2.conda
+ sha256: 7ab669b19a40047c658ff332e5b0d177d9d34032abcdf6b9b8cda806fee70347
+ md5: 2e96c94fdeb028fb413b972913ee9c35
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _x86_64-microarch-level >=1
+ - giflib >=5.2.2,<5.3.0a0
+ - icu >=75.1,<76.0a0
+ - libabseil * cxx17*
+ - libabseil >=20250512.1,<20250513.0a0
+ - libcurl >=8.17.0,<9.0a0
+ - libgcc >=14
+ - libgrpc >=1.73.1,<1.74.0a0
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - libpng >=1.6.51,<1.7.0a0
+ - libprotobuf >=6.31.1,<6.31.2.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - snappy >=1.2.2,<1.3.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 9265067
+ timestamp: 1764396133215
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtensorflow_framework-2.18.0-cpu_h78d15be_2.conda
+ sha256: 7b6c830c7c75c79631dec2b5b9940772668e16fd2a574b3a0fa98cbdcab243ed
+ md5: e2533059b269ac3a8bf519c023cb18b2
+ depends:
+ - giflib >=5.2.2,<5.3.0a0
+ - icu >=75.1,<76.0a0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcurl >=8.14.1,<9.0a0
+ - libgcc
+ - libgcc-ng >=12
+ - libgrpc >=1.67.1,<1.68.0a0
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - libpng >=1.6.50,<1.7.0a0
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libstdcxx
+ - libstdcxx-ng >=12
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.2,<4.0a0
+ - snappy >=1.2.2,<1.3.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 10206042
+ timestamp: 1757537863685
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtensorflow_framework-2.18.0-cpu_h2398287_1.conda
+ sha256: ffe63dcf069914d686dd8a6c7a0586f8b46b3ed84d219cefb89a5a58c2ed021f
+ md5: 3ebee6d8f4550dd64cc76fcefbd8b3a9
+ depends:
+ - __osx >=11.0
+ - giflib >=5.2.2,<5.3.0a0
+ - icu >=75.1,<76.0a0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcurl >=8.14.1,<9.0a0
+ - libcxx >=18
+ - libgrpc >=1.67.1,<1.68.0a0
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - libpng >=1.6.50,<1.7.0a0
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.2,<4.0a0
+ - snappy >=1.2.2,<1.3.0a0
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 7683489
+ timestamp: 1754497703678
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda
+ sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0
+ md5: cd5a90476766d53e901500df9215e927
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - lerc >=4.0.0,<5.0a0
+ - libdeflate >=1.25,<1.26.0a0
+ - libgcc >=14
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libstdcxx >=14
+ - libwebp-base >=1.6.0,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: HPND
+ purls: []
+ size: 435273
+ timestamp: 1762022005702
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda
+ sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39
+ md5: 8c6fd84f9c87ac00636007c6131e457d
+ depends:
+ - lerc >=4.0.0,<5.0a0
+ - libdeflate >=1.25,<1.26.0a0
+ - libgcc >=14
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libstdcxx >=14
+ - libwebp-base >=1.6.0,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: HPND
+ purls: []
+ size: 488407
+ timestamp: 1762022048105
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libtiff-4.7.1-h4030677_1.conda
+ sha256: e9248077b3fa63db94caca42c8dbc6949c6f32f94d1cafad127f9005d9b1507f
+ md5: e2a72ab2fa54ecb6abab2b26cde93500
+ depends:
+ - __osx >=11.0
+ - lerc >=4.0.0,<5.0a0
+ - libcxx >=19
+ - libdeflate >=1.25,<1.26.0a0
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libwebp-base >=1.6.0,<2.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ license: HPND
+ purls: []
+ size: 373892
+ timestamp: 1762022345545
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda
+ sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee
+ md5: db409b7c1720428638e7c0d509d3e1b5
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 40311
+ timestamp: 1766271528534
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda
+ sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11
+ md5: cf2861212053d05f27ec49c3784ff8bb
+ depends:
+ - libgcc >=14
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 43453
+ timestamp: 1766271546875
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libvulkan-loader-1.4.328.1-h5279c79_0.conda
+ sha256: bbabc5c48b63ff03f440940a11d4648296f5af81bb7630d98485405cd32ac1ce
+ md5: 372a62464d47d9e966b630ffae3abe73
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libstdcxx >=14
+ - libgcc >=14
+ - xorg-libx11 >=1.8.12,<2.0a0
+ - xorg-libxrandr >=1.5.4,<2.0a0
+ constrains:
+ - libvulkan-headers 1.4.328.1.*
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 197672
+ timestamp: 1759972155030
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libvulkan-loader-1.4.328.1-h8b8848b_0.conda
+ sha256: f1b32481c65008087c64dec21cc141dec9b80921ff2a3f5571c24c8f531b18ea
+ md5: e5a3ff3a266b68398bd28ed1d4363e65
+ depends:
+ - libstdcxx >=14
+ - libgcc >=14
+ - xorg-libxrandr >=1.5.4,<2.0a0
+ - xorg-libx11 >=1.8.12,<2.0a0
+ constrains:
+ - libvulkan-headers 1.4.328.1.*
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 214593
+ timestamp: 1759972148472
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda
+ sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b
+ md5: aea31d2e5b1091feca96fcfe945c3cf9
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ constrains:
+ - libwebp 1.6.0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 429011
+ timestamp: 1752159441324
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda
+ sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25
+ md5: 24e92d0942c799db387f5c9d7b81f1af
+ depends:
+ - libgcc >=14
+ constrains:
+ - libwebp 1.6.0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 359496
+ timestamp: 1752160685488
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libwebp-base-1.6.0-h07db88b_0.conda
+ sha256: a4de3f371bb7ada325e1f27a4ef7bcc81b2b6a330e46fac9c2f78ac0755ea3dd
+ md5: e5e7d467f80da752be17796b87fe6385
+ depends:
+ - __osx >=11.0
+ constrains:
+ - libwebp 1.6.0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 294974
+ timestamp: 1752159906788
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda
+ sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa
+ md5: 92ed62436b625154323d40d5f2f11dd7
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - pthread-stubs
+ - xorg-libxau >=1.0.11,<2.0a0
+ - xorg-libxdmcp
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 395888
+ timestamp: 1727278577118
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda
+ sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b
+ md5: cd14ee5cca2464a425b1dbfc24d90db2
+ depends:
+ - libgcc >=13
+ - pthread-stubs
+ - xorg-libxau >=1.0.11,<2.0a0
+ - xorg-libxdmcp
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 397493
+ timestamp: 1727280745441
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxcb-1.17.0-hdb1d25a_0.conda
+ sha256: bd3816218924b1e43b275863e21a3e13a5db4a6da74cca8e60bc3c213eb62f71
+ md5: af523aae2eca6dfa1c8eec693f5b9a79
+ depends:
+ - __osx >=11.0
+ - pthread-stubs
+ - xorg-libxau >=1.0.11,<2.0a0
+ - xorg-libxdmcp
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 323658
+ timestamp: 1727278733917
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda
+ sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c
+ md5: 5aa797f8787fe7a17d1b0821485b5adc
+ depends:
+ - libgcc-ng >=12
+ license: LGPL-2.1-or-later
+ purls: []
+ size: 100393
+ timestamp: 1702724383534
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda
+ sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f
+ md5: b4df5d7d4b63579d081fd3a4cf99740e
+ depends:
+ - libgcc-ng >=12
+ license: LGPL-2.1-or-later
+ purls: []
+ size: 114269
+ timestamp: 1702724369203
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libxgboost-3.1.2-cpu_h2ebb00f_2.conda
+ sha256: b435098d7eb768225faaf63ecc20806ee4151d9a1050325203675bc6d7d14e44
+ md5: eb5ce368393d4ac775590093128511b5
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _openmp_mutex >=4.5
+ - libgcc >=14
+ - libstdcxx >=14
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 3727153
+ timestamp: 1765327613209
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxgboost-3.1.2-cpu_hb699d04_2.conda
+ sha256: 7074a2eaf9c19bbd465b33fdaf39b47277e07bdebc0c84a5ee2619604c375a4d
+ md5: 35cdd27263ead4fbb204a7b1f4aea138
+ depends:
+ - _openmp_mutex >=4.5
+ - libgcc >=14
+ - libstdcxx >=14
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 3457850
+ timestamp: 1765327734245
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxgboost-3.1.2-cpu_h64a644d_2.conda
+ sha256: 847002772032af4184c52d9217f017e3fc8246193c3fb4b30df2e83f048f61b9
+ md5: e178e8b6ed56fac8356e3383a00b64ad
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ - llvm-openmp >=19.1.7
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 1540862
+ timestamp: 1765328228785
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.13.1-hca5e8e5_0.conda
+ sha256: d2195b5fbcb0af1ff7b345efdf89290c279b8d1d74f325ae0ac98148c375863c
+ md5: 2bca1fbb221d9c3c8e3a155784bbc2e9
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - libxcb >=1.17.0,<2.0a0
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - xkeyboard-config
+ - xorg-libxau >=1.0.12,<2.0a0
+ license: MIT/X11 Derivative
+ license_family: MIT
+ purls: []
+ size: 837922
+ timestamp: 1764794163823
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxkbcommon-1.13.1-h3c6a4c8_0.conda
+ sha256: 37e4aa45b71c35095a01835bd42fa37c08218fec44eb2c6bf4b9e2826b0351d4
+ md5: 22c1ce28d481e490f3635c1b6a2bb23f
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - libxcb >=1.17.0,<2.0a0
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - xkeyboard-config
+ - xorg-libxau >=1.0.12,<2.0a0
+ license: MIT/X11 Derivative
+ license_family: MIT
+ purls: []
+ size: 863646
+ timestamp: 1764794352540
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.1-h26afc86_0.conda
+ sha256: ec0735ae56c3549149eebd7dc22c0bed91fd50c02eaa77ff418613ddda190aa8
+ md5: e512be7dc1f84966d50959e900ca121f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - icu >=75.1,<76.0a0
+ - libgcc >=14
+ - libiconv >=1.18,<2.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libxml2-16 2.15.1 ha9997c6_0
+ - libzlib >=1.3.1,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 45283
+ timestamp: 1761015644057
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.1-h788dabe_0.conda
+ sha256: db0a568e0853ee38b7a4db1cb4ee76e57fe7c32ccb1d5b75f6618a1041d3c6e4
+ md5: a0e7779b7625b88e37df9bd73f0638dc
+ depends:
+ - icu >=75.1,<76.0a0
+ - libgcc >=14
+ - libiconv >=1.18,<2.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libxml2-16 2.15.1 h8591a01_0
+ - libzlib >=1.3.1,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 47192
+ timestamp: 1761015739999
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.1-ha9997c6_0.conda
+ sha256: 71436e72a286ef8b57d6f4287626ff91991eb03c7bdbe835280521791efd1434
+ md5: e7733bc6785ec009e47a224a71917e84
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - icu >=75.1,<76.0a0
+ - libgcc >=14
+ - libiconv >=1.18,<2.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - libxml2 2.15.1
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 556302
+ timestamp: 1761015637262
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.1-h8591a01_0.conda
+ sha256: 7a13450bce2eeba8f8fb691868b79bf0891377b707493a527bd930d64d9b98af
+ md5: e7177c6fbbf815da7b215b4cc3e70208
+ depends:
+ - icu >=75.1,<76.0a0
+ - libgcc >=14
+ - libiconv >=1.18,<2.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - libxml2 2.15.1
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 597078
+ timestamp: 1761015734476
+- 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: []
+ size: 245434
+ timestamp: 1757963724977
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxslt-1.1.43-h6700d25_1.conda
+ sha256: 8a816572a4650149d28c0b8b44e294380de18787735d00c7cf5fad91dba8e286
+ md5: 0f31501ccd51a40f0a91381080ae7368
+ depends:
+ - libgcc >=14
+ - libxml2
+ - libxml2-16 >=2.14.6
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 253367
+ timestamp: 1757964660396
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
+ sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4
+ md5: edb0dca6bc32e4f4789199455a1dbeb8
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ constrains:
+ - zlib 1.3.1 *_2
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 60963
+ timestamp: 1727963148474
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda
+ sha256: 5a2c1eeef69342e88a98d1d95bff1603727ab1ff4ee0e421522acd8813439b84
+ md5: 08aad7cbe9f5a6b460d0976076b6ae64
+ depends:
+ - libgcc >=13
+ constrains:
+ - zlib 1.3.1 *_2
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 66657
+ timestamp: 1727963199518
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda
+ sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b
+ md5: 369964e85dc26bfe78f41399b366c435
+ depends:
+ - __osx >=11.0
+ constrains:
+ - zlib 1.3.1 *_2
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 46438
+ timestamp: 1727963202283
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda
+ sha256: 56bcd20a0a44ddd143b6ce605700fdf876bcf5c509adc50bf27e76673407a070
+ md5: 206ad2df1b5550526e386087bef543c7
+ depends:
+ - __osx >=11.0
+ constrains:
+ - openmp 21.1.8|21.1.8.*
+ - intel-openmp <0.0a0
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: APACHE
+ purls: []
+ size: 285974
+ timestamp: 1765964756583
+- pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl
+ name: logistro
+ version: 2.0.1
+ sha256: 06ffa127b9fb4ac8b1972ae6b2a9d7fde57598bf5939cd708f43ec5bba2d31eb
+ requires_python: '>=3.8'
+- conda: https://conda.anaconda.org/conda-forge/noarch/mako-1.3.10-pyhcf101f3_1.conda
+ sha256: 6099a13faaaf22afa8daa273929f393d41140fc03509b4ef1e2f6858b511699d
+ md5: 99f74609a309e434f25f0ede5f50580c
+ depends:
+ - python >=3.10
+ - importlib-metadata
+ - markupsafe >=0.9.2
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/mako?source=hash-mapping
+ size: 71947
+ timestamp: 1764678340587
+- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10-pyhcf101f3_1.conda
+ sha256: 32af5d32e3193b7c0ea02c33cc8753bfc0965d07e1aa58418a851d0bb94a7792
+ md5: 934afb77580165027b869d4104ee002f
+ depends:
+ - importlib-metadata >=4.4
+ - python >=3.10
+ - python
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/markdown?source=hash-mapping
+ size: 85401
+ timestamp: 1762856570927
+- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda
+ sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e
+ md5: 5b5203189eb668f042ac2b0826244964
+ depends:
+ - mdurl >=0.1,<1
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/markdown-it-py?source=hash-mapping
+ size: 64736
+ timestamp: 1754951288511
+- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_0.conda
+ sha256: f77f9f1a4da45cbc8792d16b41b6f169f649651a68afdc10b2da9da12b9aa42b
+ md5: f775a43412f7f3d7ed218113ad233869
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - jinja2 >=3.0.0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/markupsafe?source=hash-mapping
+ size: 25321
+ timestamp: 1759055268795
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py312hd077ced_0.conda
+ sha256: f35cf61ae7fbb3ed0529f000b4bc9999ac0bed8803654ed2db889a394d9853c2
+ md5: d4e5ac7000bdc398b3cfba57f01e7e63
+ depends:
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - jinja2 >=3.0.0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/markupsafe?source=hash-mapping
+ size: 25943
+ timestamp: 1759056553164
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h5748b74_0.conda
+ sha256: b6aadcee6a0b814a0cb721e90575cbbe911b17ec46542460a9416ed2ec1a568e
+ md5: 82221456841d3014a175199e4792465b
+ depends:
+ - __osx >=11.0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - jinja2 >=3.0.0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/markupsafe?source=hash-mapping
+ size: 25121
+ timestamp: 1759055677633
+- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-3.10.8-py312h7900ff3_0.conda
+ sha256: 6d66175e1a4ffb91ed954e2c11066d2e03a05bce951a808275069836ddfc993e
+ md5: 2a7663896e5aab10b60833a768c4c272
+ depends:
+ - matplotlib-base >=3.10.8,<3.10.9.0a0
+ - pyside6 >=6.7.2
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tornado >=5
+ license: PSF-2.0
+ license_family: PSF
+ purls: []
+ size: 17415
+ timestamp: 1763055550515
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-3.10.8-py312h8025657_0.conda
+ sha256: 1b5df01734c77e5e0665a7ecfe01f5f815745ab8b88d2c0c4b7cff79b86f39cd
+ md5: 293872f5b213932c9b35ee195c3ed175
+ depends:
+ - matplotlib-base >=3.10.8,<3.10.9.0a0
+ - pyside6 >=6.7.2
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tornado >=5
+ license: PSF-2.0
+ license_family: PSF
+ purls: []
+ size: 17597
+ timestamp: 1763055556020
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-3.10.8-py312h1f38498_0.conda
+ sha256: e3e8448b10273807bf1aa9b1aa6a4ee3a686ccfd0c296560b51b1d1581bb42ae
+ md5: 534ed7eb4471c088285fdb382805e6ef
+ depends:
+ - matplotlib-base >=3.10.8,<3.10.9.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tornado >=5
+ license: PSF-2.0
+ license_family: PSF
+ purls: []
+ size: 17526
+ timestamp: 1763060540928
+- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.10.8-py312he3d6523_0.conda
+ sha256: 70cf0e7bfd50ef50eb712a6ca1eef0ef0d63b7884292acc81353327b434b548c
+ md5: b8dc157bbbb69c1407478feede8b7b42
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - contourpy >=1.0.1
+ - cycler >=0.10
+ - fonttools >=4.22.0
+ - freetype
+ - kiwisolver >=1.3.1
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.23
+ - numpy >=1.23,<3
+ - packaging >=20.0
+ - pillow >=8
+ - pyparsing >=2.3.1
+ - python >=3.12,<3.13.0a0
+ - python-dateutil >=2.7
+ - python_abi 3.12.* *_cp312
+ - 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
+ size: 8442149
+ timestamp: 1763055517581
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/matplotlib-base-3.10.8-py312h9d0c5ba_0.conda
+ sha256: e8fd4979f8f89fa86a9768f10ee116dd1a3c6f018e55c535a15729b8dfaf097d
+ md5: 970c9ee448eab5a3166041012044b5ee
+ depends:
+ - contourpy >=1.0.1
+ - cycler >=0.10
+ - fonttools >=4.22.0
+ - freetype
+ - kiwisolver >=1.3.1
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.23
+ - numpy >=1.23,<3
+ - packaging >=20.0
+ - pillow >=8
+ - pyparsing >=2.3.1
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python-dateutil >=2.7
+ - python_abi 3.12.* *_cp312
+ - 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
+ size: 8209226
+ timestamp: 1763055536845
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/matplotlib-base-3.10.8-py312h605b88b_0.conda
+ sha256: 3c96c85dd723a4c16fce4446d1f0dc7d64e46b6ae4629c66d65984b8593ee999
+ md5: fbc4f90b3d63ea4e6c30f7733a0b5bfd
+ depends:
+ - __osx >=11.0
+ - contourpy >=1.0.1
+ - cycler >=0.10
+ - fonttools >=4.22.0
+ - freetype
+ - kiwisolver >=1.3.1
+ - libcxx >=19
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - numpy >=1.23
+ - numpy >=1.23,<3
+ - packaging >=20.0
+ - pillow >=8
+ - pyparsing >=2.3.1
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python-dateutil >=2.7
+ - python_abi 3.12.* *_cp312
+ - qhull >=2020.2,<2020.3.0a0
+ license: PSF-2.0
+ license_family: PSF
+ purls:
+ - pkg:pypi/matplotlib?source=hash-mapping
+ size: 8243636
+ timestamp: 1763060482877
+- conda: https://conda.anaconda.org/conda-forge/noarch/mccabe-0.7.0-pyhd8ed1ab_1.conda
+ sha256: 9b0037171dad0100f0296699a11ae7d355237b55f42f9094aebc0f41512d96a1
+ md5: 827064ddfe0de2917fb29f1da4f8f533
+ depends:
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/mccabe?source=hash-mapping
+ size: 12934
+ timestamp: 1733216573915
+- 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
+ size: 14465
+ timestamp: 1733255681319
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ml_dtypes-0.5.4-np2py312h0f77346_0.conda
+ sha256: a85c18c5526acce27758943a33d440bcb33aa73a31aae01cbb9b5a088ba4b963
+ md5: e595b02dca6bcc8257df8f94eb3d9903
+ depends:
+ - python
+ - libstdcxx >=14
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - numpy >=1.23,<3
+ - python_abi 3.12.* *_cp312
+ license: MPL-2.0 AND Apache-2.0
+ purls:
+ - pkg:pypi/ml-dtypes?source=hash-mapping
+ size: 344917
+ timestamp: 1764068356648
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ml_dtypes-0.4.0-py312ha2895bd_2.conda
+ sha256: fd61afa9c8d9cbc73f98f4bd0da923d6e997b46c66672f0e862b6e4b7c371ef0
+ md5: 74139202709fb94009c9e3020d9b639c
+ depends:
+ - libgcc >=13
+ - libstdcxx >=13
+ - numpy >=1.19,<3
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: MPL-2.0 AND Apache-2.0
+ purls:
+ - pkg:pypi/ml-dtypes?source=hash-mapping
+ size: 152040
+ timestamp: 1725475268570
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ml_dtypes-0.4.0-py312hcd31e36_2.conda
+ sha256: 3931aef8f1e04f2fd9cff55a0c8dd76f818a3eb4fad5ef6cfd83649d14a663e4
+ md5: 70b338acc912c1989a36ed8511f884a7
+ depends:
+ - __osx >=11.0
+ - libcxx >=17
+ - numpy >=1.19,<3
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: MPL-2.0 AND Apache-2.0
+ purls:
+ - pkg:pypi/ml-dtypes?source=hash-mapping
+ size: 123771
+ timestamp: 1725475270272
+- conda: https://conda.anaconda.org/conda-forge/linux-64/mpc-1.3.1-h24ddda3_1.conda
+ sha256: 1bf794ddf2c8b3a3e14ae182577c624fa92dea975537accff4bc7e5fea085212
+ md5: aa14b9a5196a6d8dd364164b7ce56acf
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - gmp >=6.3.0,<7.0a0
+ - libgcc >=13
+ - mpfr >=4.2.1,<5.0a0
+ license: LGPL-3.0-or-later
+ license_family: LGPL
+ purls: []
+ size: 116777
+ timestamp: 1725629179524
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mpc-1.3.1-h783934e_1.conda
+ sha256: b5b674f496ed28c0b2d08533c6f11eaf1840bf7d9c830655f51514f2f9d9a9c8
+ md5: d3758cd24507dc1bda3483ce051d48ac
+ depends:
+ - gmp >=6.3.0,<7.0a0
+ - libgcc >=13
+ - mpfr >=4.2.1,<5.0a0
+ license: LGPL-3.0-or-later
+ license_family: LGPL
+ purls: []
+ size: 132799
+ timestamp: 1725629168783
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/mpc-1.3.1-h8f1351a_1.conda
+ sha256: 2700899ad03302a1751dbf2bca135407e470dd83ac897ab91dd8675d4300f158
+ md5: a5635df796b71f6ca400fc7026f50701
+ depends:
+ - __osx >=11.0
+ - gmp >=6.3.0,<7.0a0
+ - mpfr >=4.2.1,<5.0a0
+ license: LGPL-3.0-or-later
+ license_family: LGPL
+ purls: []
+ size: 104766
+ timestamp: 1725629165420
+- conda: https://conda.anaconda.org/conda-forge/linux-64/mpfr-4.2.1-h90cbb55_3.conda
+ sha256: f25d2474dd557ca66c6231c8f5ace5af312efde1ba8290a6ea5e1732a4e669c0
+ md5: 2eeb50cab6652538eee8fc0bc3340c81
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - gmp >=6.3.0,<7.0a0
+ - libgcc >=13
+ license: LGPL-3.0-only
+ license_family: LGPL
+ purls: []
+ size: 634751
+ timestamp: 1725746740014
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mpfr-4.2.1-h2305555_3.conda
+ sha256: abb35c37de2ec6c9ee89995142b1cfea9e6547202ba5578e5307834eca6d436f
+ md5: 65b21e8d5f0ec6a2f7e87630caed3318
+ depends:
+ - gmp >=6.3.0,<7.0a0
+ - libgcc >=13
+ license: LGPL-3.0-only
+ license_family: LGPL
+ purls: []
+ size: 1841314
+ timestamp: 1725746723157
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/mpfr-4.2.1-hb693164_3.conda
+ sha256: 4463e4e2aba7668e37a1b8532859191b4477a6f3602a5d6b4d64ad4c4baaeac5
+ md5: 4e4ea852d54cc2b869842de5044662fb
+ depends:
+ - __osx >=11.0
+ - gmp >=6.3.0,<7.0a0
+ license: LGPL-3.0-only
+ license_family: LGPL
+ purls: []
+ size: 345517
+ timestamp: 1725746730583
+- conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda
+ sha256: 7d7aa3fcd6f42b76bd711182f3776a02bef09a68c5f117d66b712a6d81368692
+ md5: 3585aa87c43ab15b167b574cd73b057b
+ depends:
+ - python >=3.9
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/mpmath?source=hash-mapping
+ size: 439705
+ timestamp: 1733302781386
+- conda: https://conda.anaconda.org/conda-forge/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
+ size: 15851
+ timestamp: 1749895533014
+- conda: https://conda.anaconda.org/conda-forge/noarch/namex-0.1.0-pyhd8ed1ab_0.conda
+ sha256: 295e0ef6aae0185b55752c981eca5c11443ba9ea4c236d45112128799fd99f51
+ md5: 3eb854547a0183b994431957fa0e05d2
+ depends:
+ - python >=3.9
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/namex?source=hash-mapping
+ size: 11936
+ timestamp: 1748346473739
+- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.14.0-pyhcf101f3_0.conda
+ sha256: 793f9f99d9c4f31fd56632dfd085ba4d5e7eca5bf6373613a21af66a034cc8f1
+ md5: 2708dffa2a43a303f5f9cb020fedb6ab
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/narwhals?source=hash-mapping
+ size: 271314
+ timestamp: 1765893898943
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
+ sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586
+ md5: 47e340acb35de30501a76c7c799c41d7
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ license: X11 AND BSD-3-Clause
+ purls: []
+ size: 891641
+ timestamp: 1738195959188
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda
+ sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468
+ md5: 182afabe009dc78d8b73100255ee6868
+ depends:
+ - libgcc >=13
+ license: X11 AND BSD-3-Clause
+ purls: []
+ size: 926034
+ timestamp: 1738196018799
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda
+ sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733
+ md5: 068d497125e4bf8a66bf707254fff5ae
+ depends:
+ - __osx >=11.0
+ license: X11 AND BSD-3-Clause
+ purls: []
+ size: 797030
+ timestamp: 1738196177597
+- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.0-py312h33ff503_0.conda
+ sha256: 3e6cf18f30c2dcd3a4d1a388157007deb1fbd09ea6916dc59938c872a261858e
+ md5: 4ba148299453b88d8fa9b6351eaa0df8
+ depends:
+ - python
+ - libgcc >=14
+ - libstdcxx >=14
+ - __glibc >=2.17,<3.0.a0
+ - liblapack >=3.9.0,<4.0a0
+ - libcblas >=3.9.0,<4.0a0
+ - python_abi 3.12.* *_cp312
+ - libblas >=3.9.0,<4.0a0
+ constrains:
+ - numpy-base <0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/numpy?source=compressed-mapping
+ size: 8752159
+ timestamp: 1766373912985
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.0-py312h6615c27_0.conda
+ sha256: 68b71eb6d7337b8bfb5c62200e9779cb47efa26fd9f1eede324103418d825abf
+ md5: f7364ff4be001783fdbdd98cfd9f1194
+ depends:
+ - python
+ - libstdcxx >=14
+ - libgcc >=14
+ - python 3.12.* *_cpython
+ - libblas >=3.9.0,<4.0a0
+ - python_abi 3.12.* *_cp312
+ - 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
+ size: 7835920
+ timestamp: 1766373914372
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.4.0-py312he281c53_0.conda
+ sha256: c4174ca8b54e0113748c21e6222238cff3f8b3bac49f7fa64cc4b9e554b29b7a
+ md5: 077fc6ec945d1d90729342a47dbef6c0
+ depends:
+ - python
+ - python 3.12.* *_cpython
+ - libcxx >=19
+ - __osx >=11.0
+ - liblapack >=3.9.0,<4.0a0
+ - libcblas >=3.9.0,<4.0a0
+ - libblas >=3.9.0,<4.0a0
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - numpy-base <0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/numpy?source=hash-mapping
+ size: 6830370
+ timestamp: 1766373807397
+- conda: https://conda.anaconda.org/conda-forge/linux-64/onnx-1.20.0-py312h75e9504_1.conda
+ sha256: 4812865de2df791d3fc75fe5072ae00ec40e6de80d0c56cb4bc8aae4995fd70f
+ md5: 480019c7fb2d50f6f4960ea51323bbe2
+ depends:
+ - python
+ - ml_dtypes
+ - protobuf
+ - typing_extensions
+ - libstdcxx >=14
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ - python_abi 3.12.* *_cp312
+ - libprotobuf >=6.31.1,<6.31.2.0a0
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/onnx?source=hash-mapping
+ size: 11008369
+ timestamp: 1766944796386
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/onnx-1.17.0-py312hf4577d9_2.conda
+ sha256: 5313ae70c5552bce89bb3d3213c2c0a285f1e8879d727058ae25cdc048380501
+ md5: 5038f332402e957eede26494112071d1
+ depends:
+ - libgcc >=13
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libstdcxx >=13
+ - numpy >=1.19,<3
+ - protobuf
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/onnx?source=hash-mapping
+ size: 11522694
+ timestamp: 1735636747797
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/onnx-1.17.0-py312hc636692_2.conda
+ sha256: 852b87a74e30c46a8f82b64fc6eb3b6d25079b00d86ae6b0496fcc9b6ed34bae
+ md5: 0b816200a58498e890ce876b92ec469e
+ depends:
+ - __osx >=11.0
+ - libcxx >=18
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - numpy >=1.19,<3
+ - protobuf
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/onnx?source=hash-mapping
+ size: 10709005
+ timestamp: 1735632496387
+- conda: https://conda.anaconda.org/conda-forge/noarch/onnxconverter-common-1.16.0-pyhd8ed1ab_0.conda
+ sha256: ffd5ed59f175914ebeddd5a54ebcdebf81194bc761a0c91ef8e3b77ecd735c75
+ md5: 5e2a5234325b5552f6a84886ecc78554
+ depends:
+ - numpy
+ - onnx
+ - packaging
+ - protobuf >=3.20.2
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/onnxconverter-common?source=hash-mapping
+ size: 75719
+ timestamp: 1764157622533
+- conda: https://conda.anaconda.org/conda-forge/noarch/onnxmltools-1.14.0-pyhe01879c_0.conda
+ sha256: 2e7e5716f5f07549014fe35969831b28612ad691c715e92d3d5029e2bef08ace
+ md5: 57599d2d5159f9121f10ad96194612d3
+ depends:
+ - python >=3.9
+ - numpy
+ - onnx
+ - skl2onnx
+ - python
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/onnxmltools?source=hash-mapping
+ size: 211688
+ timestamp: 1749594206560
+- conda: https://conda.anaconda.org/conda-forge/linux-64/onnxruntime-1.22.2-py312hb39aaa6_1_cpu.conda
+ build_number: 1
+ sha256: d1a361511caddc2c82e3b88fb22d59861a0c644a39f385b26a1e1234d22e1776
+ md5: a49594bd3bab2e2e7426f5f5eeea60a5
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - coloredlogs
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.23,<3
+ - packaging
+ - protobuf
+ - python >=3.12,<3.13.0a0
+ - python-flatbuffers
+ - python_abi 3.12.* *_cp312
+ - sympy
+ license: MIT AND BSL-1.0
+ purls:
+ - pkg:pypi/onnxruntime?source=hash-mapping
+ size: 13487738
+ timestamp: 1765364559327
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/onnxruntime-1.22.2-py312hc28d7f2_1_cpu.conda
+ build_number: 1
+ sha256: ae3d08e062a4b714493c633053627bf54890c6643639ef91d89b4e2ab8d1c3b7
+ md5: dde5b2460176924f3e540203972e859f
+ depends:
+ - coloredlogs
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.23,<3
+ - packaging
+ - protobuf
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python-flatbuffers
+ - python_abi 3.12.* *_cp312
+ - sympy
+ license: MIT AND BSL-1.0
+ purls:
+ - pkg:pypi/onnxruntime?source=hash-mapping
+ size: 12008325
+ timestamp: 1765376969231
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/onnxruntime-1.22.2-py312h4d4766a_1_cpu.conda
+ build_number: 1
+ sha256: fb467cbd6e1effd41a08043328bd0ece3a237241e5145c8f446baa5704c23e6b
+ md5: 1115bd34eea0a13a7ce145396388eec8
+ depends:
+ - __osx >=11.0
+ - coloredlogs
+ - libcxx >=19
+ - numpy >=1.23,<3
+ - packaging
+ - protobuf
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python-flatbuffers
+ - python_abi 3.12.* *_cp312
+ - sympy
+ license: MIT AND BSL-1.0
+ purls:
+ - pkg:pypi/onnxruntime?source=hash-mapping
+ size: 10884960
+ timestamp: 1765302251225
+- 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: []
+ size: 355400
+ timestamp: 1758489294972
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda
+ sha256: bd1bc8bdde5e6c5cbac42d462b939694e40b59be6d0698f668515908640c77b8
+ md5: cea962410e327262346d48d01f05936c
+ depends:
+ - 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: []
+ size: 392636
+ timestamp: 1758489353577
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda
+ sha256: dd73e8f1da7dd6a5494c5586b835cbe2ec68bace55610b1c4bf927400fe9c0d7
+ md5: 6bf3d24692c157a41c01ce0bd17daeea
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ - libpng >=1.6.50,<1.7.0a0
+ - libtiff >=4.7.1,<4.8.0a0
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-2-Clause
+ license_family: BSD
+ purls: []
+ size: 319967
+ timestamp: 1758489514651
+- conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-he970967_0.conda
+ sha256: cb0b07db15e303e6f0a19646807715d28f1264c6350309a559702f4f34f37892
+ md5: 2e5bf4f1da39c0b32778561c3c4e5878
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - cyrus-sasl >=2.1.27,<3.0a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=13
+ - libstdcxx >=13
+ - openssl >=3.5.0,<4.0a0
+ license: OLDAP-2.8
+ license_family: BSD
+ purls: []
+ size: 780253
+ timestamp: 1748010165522
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openldap-2.6.10-h30c48ee_0.conda
+ sha256: 13c7ba058b6e151468111235218158083b9e867738e66a5afb96096c5c123348
+ md5: 48f31a61be512ec1929f4b4a9cedf4bd
+ depends:
+ - cyrus-sasl >=2.1.27,<3.0a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libgcc >=13
+ - libstdcxx >=13
+ - openssl >=3.5.0,<4.0a0
+ license: OLDAP-2.8
+ license_family: BSD
+ purls: []
+ size: 902902
+ timestamp: 1748010210718
+- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda
+ sha256: a47271202f4518a484956968335b2521409c8173e123ab381e775c358c67fe6d
+ md5: 9ee58d5c534af06558933af3c845a780
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - ca-certificates
+ - libgcc >=14
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 3165399
+ timestamp: 1762839186699
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.0-h8e36d6e_0.conda
+ sha256: 8dd3b4c31fe176a3e51c5729b2c7f4c836a2ce3bd5c82082dc2a503ba9ee0af3
+ md5: 7624c6e01aecba942e9115e0f5a2af9d
+ depends:
+ - ca-certificates
+ - libgcc >=14
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 3705625
+ timestamp: 1762841024958
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda
+ sha256: ebe93dafcc09e099782fe3907485d4e1671296bc14f8c383cb6f3dfebb773988
+ md5: b34dc4172653c13dcf453862f251af2b
+ depends:
+ - __osx >=11.0
+ - ca-certificates
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 3108371
+ timestamp: 1762839712322
+- conda: https://conda.anaconda.org/conda-forge/noarch/opt_einsum-3.4.0-pyhd8ed1ab_1.conda
+ sha256: af71aabb2bfa4b2c89b7b06403e5cec23b418452cae9f9772bd7ac3f9ea1ff44
+ md5: 52919815cd35c4e1a0298af658ccda04
+ depends:
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/opt-einsum?source=hash-mapping
+ size: 62479
+ timestamp: 1733688053334
+- conda: https://conda.anaconda.org/conda-forge/linux-64/optree-0.18.0-py312hd9148b4_0.conda
+ sha256: f34a33825d0e925c6b0e09c81632657935e2c0cc595d2a70d9902c7b9f891a51
+ md5: 4d4148297810361256ebf85b17693dff
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - typing-extensions >=4.12
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/optree?source=hash-mapping
+ size: 444884
+ timestamp: 1763124490090
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/optree-0.18.0-py312h4f740d2_0.conda
+ sha256: ca79b06727df3cbf8e3d7b48bd5cb9de14794be11a8af9a74bc4cda222fb8ec7
+ md5: a8102b4838437658499a3093bc57143f
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - typing-extensions >=4.12
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/optree?source=hash-mapping
+ size: 410763
+ timestamp: 1763124490264
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/optree-0.18.0-py312h84eede6_0.conda
+ sha256: 7497c12d56fde35509acae73f91eb602e8cf6abb4ff8483525684b76e8b01f10
+ md5: 5e75b9a5f0eeb12b8bd45446ed3b1d1e
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - typing-extensions >=4.12
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/optree?source=hash-mapping
+ size: 390301
+ timestamp: 1763124958546
+- conda: https://conda.anaconda.org/conda-forge/noarch/optuna-4.6.0-pyhd8ed1ab_0.conda
+ sha256: f32910cc7d7ecf88bb8bb2e1eb3207f5136d92b0f1a067dd9c2b6e31cfc7147b
+ md5: 8c297779397f7dfb3c9ad1d730094a4f
+ depends:
+ - alembic >=1.5.0
+ - colorlog
+ - numpy
+ - packaging >=20.0
+ - python >=3.9
+ - pyyaml
+ - sqlalchemy >=1.4.2
+ - tqdm
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/optuna?source=hash-mapping
+ size: 250236
+ timestamp: 1762762371297
+- pypi: https://files.pythonhosted.org/packages/6a/86/7cdb7d23dfa2aec23ba63d51839e520489424a9ed7ded79e6c0e40783bf7/optuna_integration-4.6.0-py3-none-any.whl
+ name: optuna-integration
+ version: 4.6.0
+ sha256: a02ef2018c02d521d23e364110579c03e53a518894d9b9a76b246b5fb2e027fd
+ requires_dist:
+ - optuna
+ - pytest ; extra == 'test'
+ - coverage ; extra == 'test'
+ - fakeredis[lua] ; extra == 'test'
+ - grpcio ; extra == 'test'
+ - protobuf>=5.28.1 ; extra == 'test'
+ - black<25.9.0 ; extra == 'checking'
+ - blackdoc<0.4.2 ; extra == 'checking'
+ - hacking ; extra == 'checking'
+ - isort ; extra == 'checking'
+ - mypy ; extra == 'checking'
+ - types-pyyaml ; extra == 'checking'
+ - types-redis ; extra == 'checking'
+ - types-setuptools ; extra == 'checking'
+ - typing-extensions>=3.10.0.0 ; extra == 'checking'
+ - mlflow ; extra == 'document'
+ - pandas ; extra == 'document'
+ - scikit-learn>=0.24.2 ; extra == 'document'
+ - scipy>=1.9.2 ; python_full_version >= '3.9' and extra == 'document'
+ - sphinx ; extra == 'document'
+ - sphinx-notfound-page ; extra == 'document'
+ - sphinx-rtd-theme ; extra == 'document'
+ - allennlp ; extra == 'allennlp'
+ - jsonnet ; extra == 'allennlp'
+ - numpy<2.0.0 ; extra == 'allennlp'
+ - psutil ; extra == 'allennlp'
+ - chainer ; extra == 'chainer'
+ - numpy<2.0.0 ; extra == 'chainer'
+ - chainermn ; extra == 'chainermn'
+ - numpy<2.0.0 ; extra == 'chainermn'
+ - botorch<0.10.0 ; extra == 'botorch'
+ - numpy<2.0.0 ; extra == 'catboost'
+ - catboost ; extra == 'catboost'
+ - numpy<2.0.0 ; extra == 'cma'
+ - cma ; extra == 'cma'
+ - comet-ml>=3.39.3 ; extra == 'comet'
+ - distributed ; extra == 'dask'
+ - fastai>=2.0.0 ; extra == 'fastai'
+ - fastai>=2.0.0 ; extra == 'fastaiv2'
+ - tensorflow ; extra == 'keras'
+ - lightgbm ; extra == 'lightgbm'
+ - scikit-learn ; extra == 'lightgbm'
+ - mlflow ; extra == 'mlflow'
+ - mxnet ; extra == 'mxnet'
+ - gpytorch ; extra == 'pytorch-distributed'
+ - gpytorch ; extra == 'pytorch-distributed'
+ - pytorch-ignite ; extra == 'pytorch-ignite'
+ - pytorch-ignite ; extra == 'pytorch-ignite'
+ - lightning ; extra == 'pytorch-lightning'
+ - lightning ; extra == 'pytorch-lightning'
+ - numpy<2.0.0 ; extra == 'shap'
+ - shap ; extra == 'shap'
+ - pandas ; extra == 'sklearn'
+ - scikit-learn ; extra == 'sklearn'
+ - scipy ; extra == 'sklearn'
+ - skorch ; extra == 'skorch'
+ - tensorboard ; extra == 'tensorboard'
+ - tensorflow ; extra == 'tensorboard'
+ - tensorflow<=2.15.0 ; extra == 'tensorflow'
+ - tensorflow ; extra == 'tfkeras'
+ - wandb ; extra == 'wandb'
+ - xgboost ; extra == 'xgboost'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/46/bf/0993b5a056759ba65145effe3a79dd5a939d4a070eaa5da2ee3180fbb13f/orjson-3.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ name: orjson
+ version: 3.11.5
+ sha256: c74099c6b230d4261fdc3169d50efc09abf38ace1a42ea2f9994b1d79153d477
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/52/8d/544e77d7a29d90cf4d9eecd0ae801c688e7f3d1adfa2ebae5e1e94d38ab9/orjson-3.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ name: orjson
+ version: 3.11.5
+ sha256: ed24250e55efbcb0b35bed7caaec8cedf858ab2f9f2201f17b8938c618c8ca6f
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/ef/a4/8052a029029b096a78955eadd68ab594ce2197e24ec50e6b6d2ab3f4e33b/orjson-3.11.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl
+ name: orjson
+ version: 3.11.5
+ sha256: 334e5b4bff9ad101237c2d799d9fd45737752929753bf4faf4b207335a416b7d
+ requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda
+ sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991
+ md5: 58335b26c38bf4a20f399384c33cbcf9
+ depends:
+ - python >=3.8
+ - python
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/packaging?source=hash-mapping
+ size: 62477
+ timestamp: 1745345660407
+- conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-2.3.3-py312hf79963d_1.conda
+ sha256: f633d5f9b28e4a8f66a6ec9c89ef1b6743b880b0511330184b4ab9b7e2dda247
+ md5: e597b3e812d9613f659b7d87ad252d18
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.22.4
+ - numpy >=1.23,<3
+ - python >=3.12,<3.13.0a0
+ - python-dateutil >=2.8.2
+ - python-tzdata >=2022.7
+ - python_abi 3.12.* *_cp312
+ - pytz >=2020.1
+ constrains:
+ - xarray >=2022.12.0
+ - qtpy >=2.3.0
+ - html5lib >=1.1
+ - pandas-gbq >=0.19.0
+ - tzdata >=2022.7
+ - fsspec >=2022.11.0
+ - fastparquet >=2022.12.0
+ - odfpy >=1.4.1
+ - pyxlsb >=1.0.10
+ - scipy >=1.10.0
+ - sqlalchemy >=2.0.0
+ - pytables >=3.8.0
+ - bottleneck >=1.3.6
+ - pyarrow >=10.0.1
+ - numexpr >=2.8.4
+ - pyqt5 >=5.15.9
+ - xlsxwriter >=3.0.5
+ - openpyxl >=3.1.0
+ - blosc >=1.21.3
+ - matplotlib >=3.6.3
+ - lxml >=4.9.2
+ - numba >=0.56.4
+ - s3fs >=2022.11.0
+ - tabulate >=0.9.0
+ - xlrd >=2.0.1
+ - gcsfs >=2022.11.0
+ - pyreadstat >=1.2.0
+ - python-calamine >=0.1.7
+ - zstandard >=0.19.0
+ - psycopg2 >=2.9.6
+ - beautifulsoup4 >=4.11.2
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/pandas?source=hash-mapping
+ size: 15099922
+ timestamp: 1759266031115
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pandas-2.3.3-py312hdc0efb6_1.conda
+ sha256: 9141d7fa8299dc0f0b14a92fd4ce03e01d0d04aa0fa06653226dcd0207f5bbb1
+ md5: f7dda316692dda5537c6c454df716c6b
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - numpy >=1.22.4
+ - numpy >=1.23,<3
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python-dateutil >=2.8.2
+ - python-tzdata >=2022.7
+ - python_abi 3.12.* *_cp312
+ - pytz >=2020.1
+ constrains:
+ - pyqt5 >=5.15.9
+ - odfpy >=1.4.1
+ - scipy >=1.10.0
+ - fsspec >=2022.11.0
+ - matplotlib >=3.6.3
+ - numexpr >=2.8.4
+ - pandas-gbq >=0.19.0
+ - pyreadstat >=1.2.0
+ - python-calamine >=0.1.7
+ - pyxlsb >=1.0.10
+ - qtpy >=2.3.0
+ - xlrd >=2.0.1
+ - fastparquet >=2022.12.0
+ - pyarrow >=10.0.1
+ - pytables >=3.8.0
+ - xarray >=2022.12.0
+ - tzdata >=2022.7
+ - xlsxwriter >=3.0.5
+ - blosc >=1.21.3
+ - tabulate >=0.9.0
+ - sqlalchemy >=2.0.0
+ - beautifulsoup4 >=4.11.2
+ - psycopg2 >=2.9.6
+ - gcsfs >=2022.11.0
+ - numba >=0.56.4
+ - openpyxl >=3.1.0
+ - zstandard >=0.19.0
+ - s3fs >=2022.11.0
+ - lxml >=4.9.2
+ - html5lib >=1.1
+ - bottleneck >=1.3.6
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/pandas?source=hash-mapping
+ size: 14774884
+ timestamp: 1759266174751
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-2.3.3-py312h5978115_2.conda
+ sha256: 93aa5b02e2394080a32fee9fb151da3384d317a42472586850abb37b28f314db
+ md5: fcbba82205afa4956c39136c68929385
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ - numpy >=1.22.4
+ - numpy >=1.23,<3
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python-dateutil >=2.8.2
+ - python-tzdata >=2022.7
+ - python_abi 3.12.* *_cp312
+ - pytz >=2020.1
+ constrains:
+ - xarray >=2022.12.0
+ - scipy >=1.10.0
+ - tabulate >=0.9.0
+ - pytables >=3.8.0
+ - xlsxwriter >=3.0.5
+ - pyxlsb >=1.0.10
+ - odfpy >=1.4.1
+ - zstandard >=0.19.0
+ - fastparquet >=2022.12.0
+ - gcsfs >=2022.11.0
+ - beautifulsoup4 >=4.11.2
+ - qtpy >=2.3.0
+ - xlrd >=2.0.1
+ - pandas-gbq >=0.19.0
+ - s3fs >=2022.11.0
+ - pyreadstat >=1.2.0
+ - tzdata >=2022.7
+ - html5lib >=1.1
+ - fsspec >=2022.11.0
+ - lxml >=4.9.2
+ - numexpr >=2.8.4
+ - blosc >=1.21.3
+ - openpyxl >=3.1.0
+ - pyarrow >=10.0.1
+ - python-calamine >=0.1.7
+ - numba >=0.56.4
+ - sqlalchemy >=2.0.0
+ - pyqt5 >=5.15.9
+ - psycopg2 >=2.9.6
+ - bottleneck >=1.3.6
+ - matplotlib >=3.6.3
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/pandas?source=hash-mapping
+ size: 13893993
+ timestamp: 1764615503244
+- pypi: https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl
+ name: patsy
+ version: 1.0.2
+ sha256: 37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a
+ requires_dist:
+ - numpy>=1.4
+ - pytest ; extra == 'test'
+ - pytest-cov ; extra == 'test'
+ - scipy ; extra == 'test'
+ requires_python: '>=3.6'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda
+ sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff
+ md5: 7a3bff861a6583f1889021facefc08b1
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - bzip2 >=1.0.8,<2.0a0
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 1222481
+ timestamp: 1763655398280
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda
+ sha256: 04df2cee95feba440387f33f878e9f655521e69f4be33a0cd637f07d3d81f0f9
+ md5: 1a30c42e32ca0ea216bd0bfe6f842f0b
+ depends:
+ - bzip2 >=1.0.8,<2.0a0
+ - libgcc >=14
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 1166552
+ timestamp: 1763655534263
+- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.0-py312h50c33e8_0.conda
+ sha256: dc15482aadc863e2b65757b13a248971e832036bf5ccd2be48d02dfe4c1cf5e0
+ md5: 923b06ad75b7acc888fa20a22dc397cd
+ depends:
+ - python
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - tk >=8.6.13,<8.7.0a0
+ - python_abi 3.12.* *_cp312
+ - libxcb >=1.17.0,<2.0a0
+ - libtiff >=4.7.1,<4.8.0a0
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - zlib-ng >=2.3.2,<2.4.0a0
+ - lcms2 >=2.17,<3.0a0
+ - openjpeg >=2.5.4,<3.0a0
+ - libwebp-base >=1.6.0,<2.0a0
+ license: HPND
+ purls:
+ - pkg:pypi/pillow?source=hash-mapping
+ size: 1029473
+ timestamp: 1767353193448
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.0-py312h3b21937_0.conda
+ sha256: abdb88d8c85c02ed0b1d7967d309ba38b2a4390a94b65859eeeb2d77d507feb2
+ md5: e54f3db6483774a598e48aefac808b38
+ depends:
+ - python
+ - libgcc >=14
+ - python 3.12.* *_cpython
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - tk >=8.6.13,<8.7.0a0
+ - zlib-ng >=2.3.2,<2.4.0a0
+ - lcms2 >=2.17,<3.0a0
+ - libxcb >=1.17.0,<2.0a0
+ - python_abi 3.12.* *_cp312
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - openjpeg >=2.5.4,<3.0a0
+ - libwebp-base >=1.6.0,<2.0a0
+ - libtiff >=4.7.1,<4.8.0a0
+ license: HPND
+ purls:
+ - pkg:pypi/pillow?source=hash-mapping
+ size: 1010269
+ timestamp: 1767353151891
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pillow-12.1.0-py312h4e908a4_0.conda
+ sha256: 8cf9e79ad0ba1206f716dd3f6ca9c48e2864882e0c514d1fe4dbfebe63f25ac0
+ md5: d831c4844e7a04eab4aa91a2c26dbbdd
+ depends:
+ - python
+ - __osx >=11.0
+ - python 3.12.* *_cpython
+ - zlib-ng >=2.3.2,<2.4.0a0
+ - python_abi 3.12.* *_cp312
+ - tk >=8.6.13,<8.7.0a0
+ - libwebp-base >=1.6.0,<2.0a0
+ - openjpeg >=2.5.4,<3.0a0
+ - lcms2 >=2.17,<3.0a0
+ - libxcb >=1.17.0,<2.0a0
+ - libtiff >=4.7.1,<4.8.0a0
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ license: HPND
+ purls:
+ - pkg:pypi/pillow?source=hash-mapping
+ size: 953450
+ timestamp: 1767353279678
+- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda
+ sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a
+ md5: c01af13bdc553d1a8fbfff6e8db075f0
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 450960
+ timestamp: 1754665235234
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda
+ sha256: e6b0846a998f2263629cfeac7bca73565c35af13251969f45d385db537a514e4
+ md5: 1587081d537bd4ae77d1c0635d465ba5
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 357913
+ timestamp: 1754665583353
+- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.1-pyhcf101f3_0.conda
+ sha256: 04c64fb78c520e5c396b6e07bc9082735a5cc28175dbe23138201d0a9441800b
+ md5: 1bd2e65c8c7ef24f4639ae6e850dacc2
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/platformdirs?source=hash-mapping
+ size: 23922
+ timestamp: 1764950726246
+- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.5.0-pyhd8ed1ab_0.conda
+ sha256: 13b06d2380fc46c299d2ae3465f90f156929b7f98597fc22b0e7ac0cfd40c20d
+ md5: 6d4c79b604d50c1140c32164f7eca72a
+ depends:
+ - narwhals >=1.15.1
+ - packaging
+ - python >=3.10
+ constrains:
+ - ipywidgets >=7.6
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/plotly?source=hash-mapping
+ size: 5179039
+ timestamp: 1763430425844
+- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ sha256: e14aafa63efa0528ca99ba568eaf506eb55a0371d12e6250aaaa61718d2eb62e
+ md5: d7585b6550ad04c8c5e21097ada2888e
+ depends:
+ - python >=3.9
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pluggy?source=compressed-mapping
+ size: 25877
+ timestamp: 1764896838868
+- pypi: ./
+ name: preface
+ version: 1.0.0.dev0
+ sha256: 4d3e1b852a7f03805569d29f5828f2067b5d22128f8d01948a64b0fc53b7d6c7
+ requires_dist:
+ - kaleido
+ - matplotlib
+ - numpy
+ - onnx
+ - onnxconverter-common
+ - onnxmltools
+ - onnxruntime
+ - optuna
+ - optuna-integration[tfkeras]
+ - pandas
+ - plotly
+ - rich
+ - scikit-learn
+ - skl2onnx
+ - statsmodels
+ - tensorflow
+ - tf2onnx
+ - typer
+ - xgboost
+ requires_python: '>=3.12,<3.13'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/protobuf-6.31.1-py312hb8af0ac_2.conda
+ sha256: 9c1dffa6371b5ae5a7659f08fa075a1a9d7b32fd11d5eaa1e7192eba4cae1207
+ md5: 2aaf8d6c729beb30d1b41964e7fb2cd6
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libabseil * cxx17*
+ - libabseil >=20250512.1,<20250513.0a0
+ - libgcc >=14
+ - libstdcxx >=14
+ - libzlib >=1.3.1,<2.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - libprotobuf 6.31.1
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/protobuf?source=hash-mapping
+ size: 479025
+ timestamp: 1760393393854
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/protobuf-5.28.3-py312h6f74592_0.conda
+ sha256: 9c575d5035c7ecb114ab9e17906c0a54087d9598dd6a2104c02fe33f0a29dd46
+ md5: 06513608c94fb1c1b17136ace77063a9
+ depends:
+ - libgcc >=13
+ - libstdcxx >=13
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - libprotobuf 5.28.3
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/protobuf?source=hash-mapping
+ size: 473242
+ timestamp: 1731366577844
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/protobuf-5.28.3-py312hd8f9ff3_0.conda
+ sha256: 9d572a97419bdace14d7c7cc8cc8c4bf2dcb22b56965dac87a27fbdb5061b926
+ md5: 5afbe52a59f04dd1fe566d0d17590d7e
+ depends:
+ - __osx >=11.0
+ - libcxx >=18
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - libprotobuf 5.28.3
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/protobuf?source=hash-mapping
+ size: 448803
+ timestamp: 1731367010746
+- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda
+ sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973
+ md5: b3c17d95b5a10c6e64a21fa17573e70e
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 8252
+ timestamp: 1726802366959
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda
+ sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba
+ md5: bb5a90c93e3bac3d5690acf76b4a6386
+ depends:
+ - libgcc >=13
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 8342
+ timestamp: 1726803319942
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pthread-stubs-0.4-hd74edd7_1002.conda
+ sha256: 8ed65e17fbb0ca944bfb8093b60086e3f9dd678c3448b5de212017394c247ee3
+ md5: 415816daf82e0b23a736a069a75e9da7
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 8381
+ timestamp: 1726802424786
+- conda: https://conda.anaconda.org/conda-forge/noarch/py-xgboost-3.1.2-cpu_pyh718b53a_2.conda
+ sha256: 30929289ffa10f41604cf55c79b79eae6fd44ae934f1e3d3465a6c513939a227
+ md5: bbbfbff7fffdd93ff767cf7b5aff5122
+ depends:
+ - libxgboost * cpu_h*_2
+ - libxgboost >=3.1.2,<3.1.3.0a0
+ - numpy
+ - python >=3.10
+ - scikit-learn
+ - scipy
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/xgboost?source=hash-mapping
+ size: 166617
+ timestamp: 1765327635611
+- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda
+ sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a
+ md5: 6b6ece66ebcae2d5f326c77ef2c5a066
+ depends:
+ - python >=3.9
+ license: BSD-2-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/pygments?source=hash-mapping
+ size: 889287
+ timestamp: 1750615908735
+- conda: https://conda.anaconda.org/conda-forge/noarch/pylint-4.0.4-pyhcf101f3_0.conda
+ sha256: ad0bb78785ab385d0afcca4a55e0226d8e6710ebad6450caa552f5fe61c2f6a0
+ md5: 3a830511a81b99b67a1206a9d29b44b3
+ depends:
+ - astroid >=4.0.2,<=4.1.0.dev0
+ - colorama >=0.4.5
+ - isort >=5,<8,!=5.13
+ - mccabe >=0.6,<0.8
+ - platformdirs >=2.2
+ - python >=3.10
+ - tomli >=1.1.0
+ - tomlkit >=0.10.1
+ - dill >=0.3.7
+ - python
+ license: GPL-2.0-or-later
+ license_family: GPL
+ purls:
+ - pkg:pypi/pylint?source=hash-mapping
+ size: 390859
+ timestamp: 1764517517150
+- conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.1-pyhcf101f3_0.conda
+ sha256: 0c70bc577f5efa87501bdc841b88f594f4d3f3a992dfb851e2130fa5c817835b
+ md5: d837065e4e0de4962c3462079c23f969
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pyparsing?source=compressed-mapping
+ size: 110235
+ timestamp: 1766475444791
+- conda: https://conda.anaconda.org/conda-forge/linux-64/pyside6-6.10.1-py312h9da60e5_0.conda
+ sha256: dccbc2674aaae31711933942fd16d87b127e6335556d5701cb760f27986f0375
+ md5: dda0a61b6186fc914cf6c1581f64229d
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libclang13 >=21.1.7
+ - libegl >=1.7.0,<2.0a0
+ - libgcc >=14
+ - libgl >=1.7.0,<2.0a0
+ - libopengl >=1.7.0,<2.0a0
+ - libstdcxx >=14
+ - libvulkan-loader >=1.4.328.1,<2.0a0
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - libxslt >=1.1.43,<2.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - qt6-main 6.10.1.*
+ - qt6-main >=6.10.1,<6.11.0a0
+ license: LGPL-3.0-only
+ license_family: LGPL
+ purls:
+ - pkg:pypi/pyside6?source=hash-mapping
+ - pkg:pypi/shiboken6?source=hash-mapping
+ size: 11606305
+ timestamp: 1765811838817
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyside6-6.10.1-py312h4810df5_0.conda
+ sha256: cff2b6998a1de0a4b1eab5b8650e7c4ff53411f801450f7befa1e805aded96b6
+ md5: c75a1e6df539da34554cf0761d455221
+ depends:
+ - libclang13 >=21.1.7
+ - libegl >=1.7.0,<2.0a0
+ - libgcc >=14
+ - libgl >=1.7.0,<2.0a0
+ - libopengl >=1.7.0,<2.0a0
+ - libstdcxx >=14
+ - libvulkan-loader >=1.4.328.1,<2.0a0
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - libxslt >=1.1.43,<2.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - qt6-main 6.10.1.*
+ - qt6-main >=6.10.1,<6.11.0a0
+ license: LGPL-3.0-only
+ license_family: LGPL
+ purls:
+ - pkg:pypi/pyside6?source=hash-mapping
+ - pkg:pypi/shiboken6?source=hash-mapping
+ size: 7310180
+ timestamp: 1765812001685
+- 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
+ size: 21085
+ timestamp: 1733217331982
+- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.4.2-pyhcf101f3_1.conda
+ sha256: 39f41a52eb6f927caf5cd42a2ff98a09bb850ce9758b432869374b6253826962
+ md5: da0c42269086f5170e2b296878ec13a6
+ depends:
+ - pygments >=2.7.2
+ - python >=3.10
+ - iniconfig >=1
+ - packaging >=20
+ - pluggy >=1.5,<2
+ - tomli >=1
+ - colorama >=0.4
+ - exceptiongroup >=1
+ - python
+ constrains:
+ - pytest-faulthandler >=2
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pytest?source=hash-mapping
+ size: 294852
+ timestamp: 1762354779909
+- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-5.0.0-pyhd8ed1ab_0.conda
+ sha256: 218306243faf3c36347131c2b36bb189daa948ac2e92c7ab52bb26cc8c157b3c
+ md5: c54c0107057d67ddf077751339ec2c63
+ depends:
+ - coverage >=5.2.1
+ - pytest >=4.6
+ - python >=3.8
+ - toml
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pytest-cov?source=hash-mapping
+ size: 25507
+ timestamp: 1711411153367
+- pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl
+ name: pytest-timeout
+ version: 2.4.0
+ sha256: c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2
+ requires_dist:
+ - pytest>=7.0.0
+ requires_python: '>=3.7'
+- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.12-hd63d673_1_cpython.conda
+ build_number: 1
+ sha256: 39898d24769a848c057ab861052e50bdc266310a7509efa3514b840e85a2ae98
+ md5: 5c00c8cea14ee8d02941cab9121dce41
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - bzip2 >=1.0.8,<2.0a0
+ - ld_impl_linux-64 >=2.36.1
+ - libexpat >=2.7.1,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - liblzma >=5.8.1,<6.0a0
+ - libnsl >=2.0.1,<2.1.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libuuid >=2.41.2,<3.0a0
+ - libxcrypt >=4.4.36
+ - libzlib >=1.3.1,<2.0a0
+ - ncurses >=6.5,<7.0a0
+ - openssl >=3.5.4,<4.0a0
+ - readline >=8.2,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ constrains:
+ - python_abi 3.12.* *_cp312
+ license: Python-2.0
+ purls: []
+ size: 31537229
+ timestamp: 1761176876216
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.12-h91f4b29_1_cpython.conda
+ build_number: 1
+ sha256: a635a01f696d4c62b739073eb241e83a35894f1aabb0f590957a05a23aa3ad28
+ md5: 823e8543dd3abc98b2982fea10f3daea
+ depends:
+ - bzip2 >=1.0.8,<2.0a0
+ - ld_impl_linux-aarch64 >=2.36.1
+ - libexpat >=2.7.1,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - liblzma >=5.8.1,<6.0a0
+ - libnsl >=2.0.1,<2.1.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libuuid >=2.41.2,<3.0a0
+ - libxcrypt >=4.4.36
+ - libzlib >=1.3.1,<2.0a0
+ - ncurses >=6.5,<7.0a0
+ - openssl >=3.5.4,<4.0a0
+ - readline >=8.2,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ constrains:
+ - python_abi 3.12.* *_cp312
+ license: Python-2.0
+ purls: []
+ size: 13683458
+ timestamp: 1761175192478
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.12-h18782d2_1_cpython.conda
+ build_number: 1
+ sha256: 626da9bb78459ce541407327d1e22ee673fd74e9103f1a0e0f4e3967ad0a23a7
+ md5: 0322f2ddca2cafbf34ef3ddbea100f73
+ depends:
+ - __osx >=11.0
+ - bzip2 >=1.0.8,<2.0a0
+ - libexpat >=2.7.1,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - liblzma >=5.8.1,<6.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libzlib >=1.3.1,<2.0a0
+ - ncurses >=6.5,<7.0a0
+ - openssl >=3.5.4,<4.0a0
+ - readline >=8.2,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ constrains:
+ - python_abi 3.12.* *_cp312
+ license: Python-2.0
+ purls: []
+ size: 12062421
+ timestamp: 1761176476561
+- 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
+ size: 233310
+ timestamp: 1751104122689
+- conda: https://conda.anaconda.org/conda-forge/noarch/python-flatbuffers-25.9.23-pyh1e1bc0e_0.conda
+ sha256: 1933243d9f839bb7bc6c9b75481b6445f50f8b727eb926086e8a2a347fb0467d
+ md5: 611207751a2c0b5b999b07b78985d7a0
+ depends:
+ - python >=3.10
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/flatbuffers?source=hash-mapping
+ size: 34827
+ timestamp: 1758880404905
+- conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda
+ sha256: 467134ef39f0af2dbb57d78cb3e4821f01003488d331a8dd7119334f4f47bfbd
+ md5: 7ead57407430ba33f681738905278d03
+ depends:
+ - python >=3.10
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/tzdata?source=compressed-mapping
+ size: 143542
+ timestamp: 1765719982349
+- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda
+ build_number: 8
+ sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809
+ md5: c3efd25ac4d74b1584d2f7a57195ddf1
+ constrains:
+ - python 3.12.* *_cpython
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 6958
+ timestamp: 1752805918820
+- conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2025.2-pyhd8ed1ab_0.conda
+ sha256: 8d2a8bf110cc1fc3df6904091dead158ba3e614d8402a83e51ed3a8aa93cdeb0
+ md5: bc8e3267d44011051f2eb14d22fb0960
+ depends:
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pytz?source=hash-mapping
+ size: 189015
+ timestamp: 1742920947249
+- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_0.conda
+ sha256: 1b3dc4c25c83093fff08b86a3574bc6b94ba355c8eba1f35d805c5e256455fc7
+ md5: fba10c2007c8b06f77c5a23ce3a635ad
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - yaml >=0.2.5,<0.3.0a0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pyyaml?source=hash-mapping
+ size: 204539
+ timestamp: 1758892248166
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py312ha4530ae_0.conda
+ sha256: 5f6af64897b820011c424a4ee5fd018277b898ff5d81f8991118b3353bd10ee9
+ md5: 428aed4a70236d95492c11da941fe1dc
+ depends:
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - yaml >=0.2.5,<0.3.0a0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pyyaml?source=hash-mapping
+ size: 197335
+ timestamp: 1758891936824
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h5748b74_0.conda
+ sha256: 690943c979a5bf014348933a68cd39e3bb9114d94371c4c5d846d2daaa82c7d9
+ md5: 6a2d7f8a026223c2fa1027c96c615752
+ depends:
+ - __osx >=11.0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - yaml >=0.2.5,<0.3.0a0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/pyyaml?source=hash-mapping
+ size: 190579
+ timestamp: 1758891996097
+- 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: []
+ size: 552937
+ timestamp: 1720813982144
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qhull-2020.2-h70be974_5.conda
+ sha256: 49f777bdf3c5e030a8c7b24c58cdfe9486b51d6ae0001841079a3228bdf9fb51
+ md5: bb138086d938e2b64f5f364945793ebf
+ depends:
+ - libgcc-ng >=12
+ - libstdcxx-ng >=12
+ license: LicenseRef-Qhull
+ purls: []
+ size: 554571
+ timestamp: 1720813941183
+- 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: []
+ size: 516376
+ timestamp: 1720814307311
+- conda: https://conda.anaconda.org/conda-forge/linux-64/qt6-main-6.10.1-h6f76662_3.conda
+ sha256: 8269ca1fc02dbd419f77ed30b6ec205897efd12813607ecb0630f075f8c5f01f
+ md5: f134a496ef494f2b6c5a26e5d739acc6
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - alsa-lib >=1.2.15.1,<1.3.0a0
+ - dbus >=1.16.2,<2.0a0
+ - double-conversion >=3.4.0,<3.5.0a0
+ - fontconfig >=2.15.0,<3.0a0
+ - fonts-conda-ecosystem
+ - harfbuzz >=12.2.0
+ - icu >=75.1,<76.0a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libclang-cpp21.1 >=21.1.7,<21.2.0a0
+ - libclang13 >=21.1.7
+ - libcups >=2.3.3,<2.4.0a0
+ - libdrm >=2.4.125,<2.5.0a0
+ - libegl >=1.7.0,<2.0a0
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - libgcc >=14
+ - libgl >=1.7.0,<2.0a0
+ - libglib >=2.86.3,<3.0a0
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - libllvm21 >=21.1.7,<21.2.0a0
+ - libpng >=1.6.53,<1.7.0a0
+ - libpq >=18.1,<19.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libstdcxx >=14
+ - libtiff >=4.7.1,<4.8.0a0
+ - libvulkan-loader >=1.4.328.1,<2.0a0
+ - libwebp-base >=1.6.0,<2.0a0
+ - libxcb >=1.17.0,<2.0a0
+ - libxkbcommon >=1.13.1,<2.0a0
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - pcre2 >=10.47,<10.48.0a0
+ - wayland >=1.24.0,<2.0a0
+ - xcb-util >=0.4.1,<0.5.0a0
+ - xcb-util-cursor >=0.1.6,<0.2.0a0
+ - xcb-util-image >=0.4.0,<0.5.0a0
+ - xcb-util-keysyms >=0.4.1,<0.5.0a0
+ - xcb-util-renderutil >=0.3.10,<0.4.0a0
+ - xcb-util-wm >=0.4.2,<0.5.0a0
+ - xorg-libice >=1.1.2,<2.0a0
+ - xorg-libsm >=1.2.6,<2.0a0
+ - xorg-libx11 >=1.8.12,<2.0a0
+ - xorg-libxcomposite >=0.4.6,<1.0a0
+ - xorg-libxcursor >=1.2.3,<2.0a0
+ - xorg-libxdamage >=1.1.6,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxrandr >=1.5.4,<2.0a0
+ - xorg-libxtst >=1.2.5,<2.0a0
+ - xorg-libxxf86vm >=1.1.6,<2.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ constrains:
+ - qt 6.10.1
+ license: LGPL-3.0-only
+ license_family: LGPL
+ purls: []
+ size: 56636216
+ timestamp: 1766349442902
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/qt6-main-6.10.1-h9c50542_3.conda
+ sha256: 413f58648f0cfb7c93eac52e7aa4247ef1fa8babd6e1336a825986b59bf3beef
+ md5: 35cdd1d3eeb2a53672f0005564c10c9d
+ depends:
+ - alsa-lib >=1.2.15.1,<1.3.0a0
+ - dbus >=1.16.2,<2.0a0
+ - double-conversion >=3.4.0,<3.5.0a0
+ - fontconfig >=2.15.0,<3.0a0
+ - fonts-conda-ecosystem
+ - harfbuzz >=12.2.0
+ - icu >=75.1,<76.0a0
+ - krb5 >=1.21.3,<1.22.0a0
+ - libclang-cpp21.1 >=21.1.7,<21.2.0a0
+ - libclang13 >=21.1.7
+ - libcups >=2.3.3,<2.4.0a0
+ - libdrm >=2.4.125,<2.5.0a0
+ - libegl >=1.7.0,<2.0a0
+ - libfreetype >=2.14.1
+ - libfreetype6 >=2.14.1
+ - libgcc >=14
+ - libgl >=1.7.0,<2.0a0
+ - libglib >=2.86.3,<3.0a0
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - libllvm21 >=21.1.7,<21.2.0a0
+ - libpng >=1.6.53,<1.7.0a0
+ - libpq >=18.1,<19.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libstdcxx >=14
+ - libtiff >=4.7.1,<4.8.0a0
+ - libvulkan-loader >=1.4.328.1,<2.0a0
+ - libwebp-base >=1.6.0,<2.0a0
+ - libxcb >=1.17.0,<2.0a0
+ - libxkbcommon >=1.13.1,<2.0a0
+ - libxml2
+ - libxml2-16 >=2.14.6
+ - libzlib >=1.3.1,<2.0a0
+ - openssl >=3.5.4,<4.0a0
+ - pcre2 >=10.47,<10.48.0a0
+ - wayland >=1.24.0,<2.0a0
+ - xcb-util >=0.4.1,<0.5.0a0
+ - xcb-util-cursor >=0.1.6,<0.2.0a0
+ - xcb-util-image >=0.4.0,<0.5.0a0
+ - xcb-util-keysyms >=0.4.1,<0.5.0a0
+ - xcb-util-renderutil >=0.3.10,<0.4.0a0
+ - xcb-util-wm >=0.4.2,<0.5.0a0
+ - xorg-libice >=1.1.2,<2.0a0
+ - xorg-libsm >=1.2.6,<2.0a0
+ - xorg-libx11 >=1.8.12,<2.0a0
+ - xorg-libxcomposite >=0.4.6,<1.0a0
+ - xorg-libxcursor >=1.2.3,<2.0a0
+ - xorg-libxdamage >=1.1.6,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxrandr >=1.5.4,<2.0a0
+ - xorg-libxtst >=1.2.5,<2.0a0
+ - xorg-libxxf86vm >=1.1.6,<2.0a0
+ - zstd >=1.5.7,<1.6.0a0
+ constrains:
+ - qt 6.10.1
+ license: LGPL-3.0-only
+ license_family: LGPL
+ purls: []
+ size: 59404266
+ timestamp: 1766346978669
+- conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2025.11.05-h5301d42_0.conda
+ sha256: 2f225ddf4a274743045aded48053af65c31721e797a45beed6774fdc783febfb
+ md5: 0227d04521bc3d28c7995c7e1f99a721
+ depends:
+ - libre2-11 2025.11.05 h7b12aa8_0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 27316
+ timestamp: 1762397780316
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2024.07.02-haa97905_2.conda
+ sha256: 040848655df9119bae5a549fb5c8956a5537120859416c1d9d0712b7bac9f12e
+ md5: 1bf0135339b4a7419a198a795d2d4be0
+ depends:
+ - libre2-11 2024.07.02 h18dbdb1_2
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 26830
+ timestamp: 1735540999398
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2024.07.02-h6589ca4_2.conda
+ sha256: 4d3799c05f8f662922a0acd129d119774760a3281b883603678e128d1cb307fb
+ md5: 7a8b4ad8c58a3408ca89d78788c78178
+ depends:
+ - libre2-11 2024.07.02 h07bc746_2
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 26861
+ timestamp: 1735541088455
+- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
+ sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002
+ md5: d7d95fc8287ea7bf33e0e7116d2b95ec
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 345073
+ timestamp: 1765813471974
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda
+ sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216
+ md5: 3d49cad61f829f4f0e0611547a9cda12
+ depends:
+ - libgcc >=14
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 357597
+ timestamp: 1765815673644
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
+ sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477
+ md5: f8381319127120ce51e081dce4865cf4
+ depends:
+ - __osx >=11.0
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ purls: []
+ size: 313930
+ timestamp: 1765813902568
+- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda
+ sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5
+ md5: c65df89a0b2e321045a9e01d1337b182
+ depends:
+ - python >=3.10
+ - certifi >=2017.4.17
+ - charset-normalizer >=2,<4
+ - idna >=2.5,<4
+ - urllib3 >=1.21.1,<3
+ - python
+ constrains:
+ - chardet >=3.0.2,<6
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/requests?source=compressed-mapping
+ size: 63602
+ timestamp: 1766926974520
+- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.2.0-pyhcf101f3_0.conda
+ sha256: edfb44d0b6468a8dfced728534c755101f06f1a9870a7ad329ec51389f16b086
+ md5: a247579d8a59931091b16a1e932bbed6
+ depends:
+ - markdown-it-py >=2.2.0
+ - pygments >=2.13.0,<3.0.0
+ - python >=3.10
+ - typing_extensions >=4.0.0,<5.0.0
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/rich?source=hash-mapping
+ size: 200840
+ timestamp: 1760026188268
+- conda: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.8.0-np2py312h3226591_1.conda
+ sha256: 23c643c37fafa14ba3f2b7a407126ea5e732a3655ea8157cf9f977098f863448
+ md5: 38decbeae260892040709cafc0514162
+ depends:
+ - python
+ - numpy >=1.24.1
+ - scipy >=1.10.0
+ - joblib >=1.3.0
+ - threadpoolctl >=3.2.0
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ - libstdcxx >=14
+ - _openmp_mutex >=4.5
+ - numpy >=1.23,<3
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/scikit-learn?source=hash-mapping
+ size: 9726193
+ timestamp: 1765801245538
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/scikit-learn-1.8.0-np2py312hca49013_1.conda
+ sha256: 6cdf1363ea485c6f7fc14c302bcea347308b4343200bda94d7a38b0dbb8c0e87
+ md5: 4ee0a99cdf60dad5d9349985e14ee737
+ depends:
+ - python
+ - numpy >=1.24.1
+ - scipy >=1.10.0
+ - joblib >=1.3.0
+ - threadpoolctl >=3.2.0
+ - libgcc >=14
+ - libstdcxx >=14
+ - _openmp_mutex >=4.5
+ - python 3.12.* *_cpython
+ - python_abi 3.12.* *_cp312
+ - numpy >=1.23,<3
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/scikit-learn?source=hash-mapping
+ size: 9686270
+ timestamp: 1765801247696
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scikit-learn-1.8.0-np2py312he5ca3e3_1.conda
+ sha256: 5f640a06e001666f9d4dca7cca992f1753e722e9f6e50899d7d250c02ddf7398
+ md5: ed7887c51edfa304c69a424279cec675
+ depends:
+ - python
+ - numpy >=1.24.1
+ - scipy >=1.10.0
+ - joblib >=1.3.0
+ - threadpoolctl >=3.2.0
+ - libcxx >=19
+ - python 3.12.* *_cpython
+ - __osx >=11.0
+ - llvm-openmp >=19.1.7
+ - numpy >=1.23,<3
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/scikit-learn?source=compressed-mapping
+ size: 9124177
+ timestamp: 1766550900752
+- conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.16.3-py312h54fa4ab_2.conda
+ sha256: 2f73242ca3164b4f305becb535a8245ff25839a42d4e62b222f866a5bf58b989
+ md5: e82683871cbc4bb257b7694f31a91327
+ 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.6
+ - numpy >=1.23,<3
+ - numpy >=1.25.2
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/scipy?source=compressed-mapping
+ size: 16666973
+ timestamp: 1766108740332
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/scipy-1.16.3-py312he5b0e10_2.conda
+ sha256: 0ef089b3471c2be2af0ba501035ae23af1597a203fadb3150c07b5780b2a8c97
+ md5: daa78c649c7140fba9a61abfa48bf7c3
+ depends:
+ - 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.6
+ - numpy >=1.23,<3
+ - numpy >=1.25.2
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/scipy?source=hash-mapping
+ size: 16754299
+ timestamp: 1766108900381
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/scipy-1.16.3-py312h39258fd_2.conda
+ sha256: beae2ee638cff6f954026d4ed7ca316fb6b4fa451af7f0ebbb83a94b832740ed
+ md5: 24765804abd9985bf6fbc57c9691479b
+ 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.6
+ - numpy >=1.23,<3
+ - numpy >=1.25.2
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/scipy?source=compressed-mapping
+ size: 13758691
+ timestamp: 1766108954684
+- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda
+ sha256: 972560fcf9657058e3e1f97186cc94389144b46dbdf58c807ce62e83f977e863
+ md5: 4de79c071274a53dcaf2a8c749d1499e
+ depends:
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/setuptools?source=hash-mapping
+ size: 748788
+ timestamp: 1748804951958
+- conda: https://conda.anaconda.org/conda-forge/noarch/shellingham-1.5.4-pyhd8ed1ab_2.conda
+ sha256: 1d6534df8e7924d9087bd388fbac5bd868c5bf8971c36885f9f016da0657d22b
+ md5: 83ea3a2ddb7a75c1b09cea582aa4f106
+ depends:
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/shellingham?source=hash-mapping
+ size: 15018
+ timestamp: 1762858315311
+- pypi: https://files.pythonhosted.org/packages/20/05/ed9b2571bbf38f1a2425391f18e3ac11cb1e91482c22d644a1640dea9da7/simplejson-3.20.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+ name: simplejson
+ version: 3.20.2
+ sha256: 979ce23ea663895ae39106946ef3d78527822d918a136dbc77b9e2b7f006237e
+ requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/97/ec/5c6db08e42f380f005d03944be1af1a6bd501cc641175429a1cbe7fb23b9/simplejson-3.20.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+ name: simplejson
+ version: 3.20.2
+ sha256: 12a6b2816b6cab6c3fd273d43b1948bc9acf708272074c8858f579c394f4cbc9
+ requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
+- pypi: https://files.pythonhosted.org/packages/ad/f1/efd09efcc1e26629e120fef59be059ce7841cc6e1f949a4db94f1ae8a918/simplejson-3.20.2-cp312-cp312-macosx_11_0_arm64.whl
+ name: simplejson
+ version: 3.20.2
+ sha256: 25ca2663d99328d51e5a138f22018e54c9162438d831e26cfc3458688616eca8
+ requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
+- 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
+ size: 18455
+ timestamp: 1753199211006
+- conda: https://conda.anaconda.org/conda-forge/noarch/skl2onnx-1.19.1-pyhe01879c_0.conda
+ sha256: b80f1523c6c2b2e88765938f6cbdb28f386ed80219b2d073823de19b103f4555
+ md5: d0e3cacee4ef9218404a9b65f7231df0
+ depends:
+ - python >=3.9
+ - numpy >=1.15
+ - onnx >=1.2.1
+ - onnxconverter-common >=1.7.0
+ - protobuf
+ - scikit-learn >=1.1
+ - scipy >=1.0
+ - packaging
+ - python
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/skl2onnx?source=hash-mapping
+ size: 217113
+ timestamp: 1748468753228
+- conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.2-h03e3b7b_1.conda
+ sha256: 48f3f6a76c34b2cfe80de9ce7f2283ecb55d5ed47367ba91e8bb8104e12b8f11
+ md5: 98b6c9dc80eb87b2519b97bcf7e578dd
+ depends:
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ - libstdcxx >=14
+ - libgcc >=14
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 45829
+ timestamp: 1762948049098
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.2-he774c54_1.conda
+ sha256: a8a79c53852fb07286407907402caa5a96b6e22b518c4f010be40647f9ee3726
+ md5: 3dec912091fb88614afa0af2712c1362
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ - libgcc >=14
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 47096
+ timestamp: 1762948094646
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.2-hada39a4_1.conda
+ sha256: cb9305ede19584115f43baecdf09a3866bfcd5bcca0d9e527bd76d9a1dbe2d8d
+ md5: fca4a2222994acd7f691e57f94b750c5
+ depends:
+ - libcxx >=19
+ - __osx >=11.0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 38883
+ timestamp: 1762948066818
+- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlalchemy-2.0.45-py312h4c3975b_0.conda
+ sha256: 0eb05f37eaa05e77e4bbd4c4e38d542b7a79e670afd9c4097f40a2ee5277638f
+ md5: 62bf6422896d094a55aa59bdf052aa1d
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - greenlet !=0.4.17
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - typing-extensions >=4.6.0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/sqlalchemy?source=hash-mapping
+ size: 3580299
+ timestamp: 1765351891054
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlalchemy-2.0.45-py312hefbd42c_0.conda
+ sha256: 412c802463b437a7cc99831640773cc231eb535d21bb628c86960c3c524917a1
+ md5: 263fcd144832e3983bc7a9774453ff24
+ depends:
+ - greenlet !=0.4.17
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - typing-extensions >=4.6.0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/sqlalchemy?source=hash-mapping
+ size: 3595101
+ timestamp: 1765354648146
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/sqlalchemy-2.0.45-py312h4409184_0.conda
+ sha256: 69dfbdbe2f460eadb219a4aece7663ca79e956042761515315be3e426236358b
+ md5: 575e19661fd58d1bf652f84f32a4b8e7
+ depends:
+ - __osx >=11.0
+ - greenlet !=0.4.17
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - typing-extensions >=4.6.0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/sqlalchemy?source=hash-mapping
+ size: 3564254
+ timestamp: 1765352667382
+- pypi: https://files.pythonhosted.org/packages/05/30/affbabf3c27fb501ec7b5808230c619d4d1a4525c07301074eb4bda92fa9/statsmodels-0.14.6-cp312-cp312-macosx_11_0_arm64.whl
+ name: statsmodels
+ version: 0.14.6
+ sha256: 26d4f0ed3b31f3c86f83a92f5c1f5cbe63fc992cd8915daf28ca49be14463a1c
+ requires_dist:
+ - numpy>=1.22.3,<3
+ - scipy>=1.8,!=1.9.2
+ - pandas>=1.4,!=2.1.0
+ - patsy>=0.5.6
+ - packaging>=21.3
+ - cython>=3.0.10 ; extra == 'build'
+ - cython>=3.0.10 ; extra == 'develop'
+ - cython>=3.0.10,<4 ; extra == 'develop'
+ - setuptools-scm[toml]~=8.0 ; extra == 'develop'
+ - matplotlib>=3 ; extra == 'develop'
+ - colorama ; extra == 'develop'
+ - joblib ; extra == 'develop'
+ - jinja2 ; extra == 'develop'
+ - pytest>=7.3.0,<8 ; extra == 'develop'
+ - pytest-randomly ; extra == 'develop'
+ - pytest-xdist ; extra == 'develop'
+ - pytest-cov ; extra == 'develop'
+ - pywinpty ; os_name == 'nt' and extra == 'develop'
+ - flake8 ; extra == 'develop'
+ - isort ; extra == 'develop'
+ - sphinx ; extra == 'docs'
+ - nbconvert ; extra == 'docs'
+ - jupyter-client ; extra == 'docs'
+ - ipykernel ; extra == 'docs'
+ - matplotlib ; extra == 'docs'
+ - nbformat ; extra == 'docs'
+ - numpydoc ; extra == 'docs'
+ - pandas-datareader ; extra == 'docs'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/48/f5/3a73b51e6450c31652c53a8e12e24eac64e3824be816c0c2316e7dbdcb7d/statsmodels-0.14.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
+ name: statsmodels
+ version: 0.14.6
+ sha256: d8c00a42863e4f4733ac9d078bbfad816249c01451740e6f5053ecc7db6d6368
+ requires_dist:
+ - numpy>=1.22.3,<3
+ - scipy>=1.8,!=1.9.2
+ - pandas>=1.4,!=2.1.0
+ - patsy>=0.5.6
+ - packaging>=21.3
+ - cython>=3.0.10 ; extra == 'build'
+ - cython>=3.0.10 ; extra == 'develop'
+ - cython>=3.0.10,<4 ; extra == 'develop'
+ - setuptools-scm[toml]~=8.0 ; extra == 'develop'
+ - matplotlib>=3 ; extra == 'develop'
+ - colorama ; extra == 'develop'
+ - joblib ; extra == 'develop'
+ - jinja2 ; extra == 'develop'
+ - pytest>=7.3.0,<8 ; extra == 'develop'
+ - pytest-randomly ; extra == 'develop'
+ - pytest-xdist ; extra == 'develop'
+ - pytest-cov ; extra == 'develop'
+ - pywinpty ; os_name == 'nt' and extra == 'develop'
+ - flake8 ; extra == 'develop'
+ - isort ; extra == 'develop'
+ - sphinx ; extra == 'docs'
+ - nbconvert ; extra == 'docs'
+ - jupyter-client ; extra == 'docs'
+ - ipykernel ; extra == 'docs'
+ - matplotlib ; extra == 'docs'
+ - nbformat ; extra == 'docs'
+ - numpydoc ; extra == 'docs'
+ - pandas-datareader ; extra == 'docs'
+ requires_python: '>=3.9'
+- pypi: https://files.pythonhosted.org/packages/81/68/dddd76117df2ef14c943c6bbb6618be5c9401280046f4ddfc9fb4596a1b8/statsmodels-0.14.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
+ name: statsmodels
+ version: 0.14.6
+ sha256: 19b58cf7474aa9e7e3b0771a66537148b2df9b5884fbf156096c0e6c1ff0469d
+ requires_dist:
+ - numpy>=1.22.3,<3
+ - scipy>=1.8,!=1.9.2
+ - pandas>=1.4,!=2.1.0
+ - patsy>=0.5.6
+ - packaging>=21.3
+ - cython>=3.0.10 ; extra == 'build'
+ - cython>=3.0.10 ; extra == 'develop'
+ - cython>=3.0.10,<4 ; extra == 'develop'
+ - setuptools-scm[toml]~=8.0 ; extra == 'develop'
+ - matplotlib>=3 ; extra == 'develop'
+ - colorama ; extra == 'develop'
+ - joblib ; extra == 'develop'
+ - jinja2 ; extra == 'develop'
+ - pytest>=7.3.0,<8 ; extra == 'develop'
+ - pytest-randomly ; extra == 'develop'
+ - pytest-xdist ; extra == 'develop'
+ - pytest-cov ; extra == 'develop'
+ - pywinpty ; os_name == 'nt' and extra == 'develop'
+ - flake8 ; extra == 'develop'
+ - isort ; extra == 'develop'
+ - sphinx ; extra == 'docs'
+ - nbconvert ; extra == 'docs'
+ - jupyter-client ; extra == 'docs'
+ - ipykernel ; extra == 'docs'
+ - matplotlib ; extra == 'docs'
+ - nbformat ; extra == 'docs'
+ - numpydoc ; extra == 'docs'
+ - pandas-datareader ; extra == 'docs'
+ requires_python: '>=3.9'
+- conda: https://conda.anaconda.org/conda-forge/noarch/sympy-1.14.0-pyh2585a3b_105.conda
+ sha256: 09d3b6ac51d437bc996ad006d9f749ca5c645c1900a854a6c8f193cbd13f03a8
+ md5: 8c09fac3785696e1c477156192d64b91
+ depends:
+ - __unix
+ - cpython
+ - gmpy2 >=2.0.8
+ - mpmath >=0.19
+ - python >=3.9
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/sympy?source=hash-mapping
+ size: 4616621
+ timestamp: 1745946173026
+- conda: https://conda.anaconda.org/conda-forge/noarch/tensorboard-2.18.0-pyhd8ed1ab_1.conda
+ sha256: 769d8c95b691586ee197845c52a3c7e6a9be7b3008650a73794bc7727b6831ac
+ md5: 90a735b377427589728e588b5241a253
+ depends:
+ - absl-py >=0.4
+ - grpcio >=1.48.2
+ - markdown >=2.6.8
+ - numpy >=1.12.0
+ - packaging
+ - protobuf >=3.19.6,!=4.24.0
+ - python >=3.9
+ - setuptools >=41.0.0
+ - six >1.9
+ - tensorboard-data-server >=0.7.0,<0.8.0
+ - werkzeug >=1.0.1
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/tensorboard?source=hash-mapping
+ size: 5188442
+ timestamp: 1733820813359
+- conda: https://conda.anaconda.org/conda-forge/noarch/tensorboard-2.19.0-pyhd8ed1ab_0.conda
+ sha256: 348a60f31eb14fd2e10f00d3c7b5036981b9b2d957cf56b1c9fecbfa6c0782d5
+ md5: 59cc119240f48dc05369fa8bea07ea05
+ depends:
+ - absl-py >=0.4
+ - grpcio >=1.48.2
+ - markdown >=2.6.8
+ - numpy >=1.12.0
+ - packaging
+ - protobuf >=3.19.6,!=4.24.0
+ - python >=3.9
+ - setuptools >=41.0.0
+ - six >1.9
+ - tensorboard-data-server >=0.7.0,<0.8.0
+ - werkzeug >=1.0.1
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/tensorboard?source=hash-mapping
+ size: 5188674
+ timestamp: 1740522550333
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tensorboard-data-server-0.7.0-py312h4eba8b5_4.conda
+ sha256: 9a3faf2dd703667683feee3cb0ecb9ed035b0a5193b95da3a633ff9da029fea9
+ md5: 7d6b10ed9058f6a97cd8007605b61c33
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - openssl >=3.5.4,<4.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - __glibc >=2.17
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/tensorboard-data-server?source=hash-mapping
+ size: 3491485
+ timestamp: 1764929907168
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorboard-data-server-0.7.0-py312hf3624cf_4.conda
+ sha256: 78986d8fc96748216b5bca50bafdc71b943c3cbd5dba06cb2d5f8f18f02f8a1e
+ md5: f268dfdb4f2931be52b7e9688a53df32
+ depends:
+ - libgcc >=14
+ - openssl >=3.5.4,<4.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - __glibc >=2.17
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/tensorboard-data-server?source=hash-mapping
+ size: 3493190
+ timestamp: 1764935416291
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorboard-data-server-0.7.0-py312h9536bd2_4.conda
+ sha256: a76bf47a5d9ad1134d6025c307773e20596f37b90682b14f1965c18f6b87a7da
+ md5: 2c911f542edf82b500cb08f6164cd3e7
+ depends:
+ - __osx >=11.0
+ - openssl >=3.5.4,<4.0a0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ constrains:
+ - __osx >=11.0
+ license: Apache-2.0
+ license_family: APACHE
+ purls:
+ - pkg:pypi/tensorboard-data-server?source=hash-mapping
+ size: 3207231
+ timestamp: 1764930138005
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tensorflow-2.19.1-cpu_py312h69ecde4_2.conda
+ sha256: 47e0ab5d4b85454b040d2197aa80396c306938531266a4e4efa520e3d865f733
+ md5: 6ed85633a453870a94c5bf58072afcbf
+ depends:
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tensorflow-base 2.19.1 cpu_py312h0afb428_2
+ - tensorflow-estimator 2.19.1 cpu_py312h6e6b5e2_2
+ track_features:
+ - tensorflow-cpu
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 50430
+ timestamp: 1764398336276
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorflow-2.18.0-cpu_py312h0267799_2.conda
+ sha256: 273edc621f61a53dda5e00945c21388e1e0fb468ec7b9f789a304edeedb31b34
+ md5: 7281a384c1b9a05ea12602f5f4d7255a
+ depends:
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tensorflow-base 2.18.0 cpu_py312h7226aab_2
+ - tensorflow-estimator 2.18.0 cpu_py312h15e21a2_2
+ track_features:
+ - tensorflow-cpu
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 41951
+ timestamp: 1757540281817
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorflow-2.18.0-cpu_py312hb6b62e0_1.conda
+ sha256: 816595f0080d58e0617bda5fee4bb3bd60be258417e1bc9a4cf70973c308aba0
+ md5: 94339beae4bae4682242df1c448d1306
+ depends:
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tensorflow-base 2.18.0 cpu_py312h81ab8d0_1
+ - tensorflow-estimator 2.18.0 cpu_py312h5e86b3d_1
+ track_features:
+ - tensorflow-cpu
+ license: Apache-2.0
+ license_family: Apache
+ purls: []
+ size: 46145
+ timestamp: 1754499440394
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tensorflow-base-2.19.1-cpu_py312h0afb428_2.conda
+ sha256: 16b24f777133ccec3a31de20b059900fd74a52dd0bd54b2cdf7081504607d336
+ md5: 798d2e923a450153a751382bafb42f78
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _x86_64-microarch-level >=1
+ - absl-py >=1.0.0
+ - astunparse >=1.6.0
+ - flatbuffers >=25.2.10,<25.2.11.0a0
+ - gast >=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
+ - giflib >=5.2.2,<5.3.0a0
+ - google-pasta >=0.1.1
+ - grpcio 1.73.*
+ - h5py >=3.11
+ - icu >=75.1,<76.0a0
+ - keras >=3.5
+ - libabseil * cxx17*
+ - libabseil >=20250512.1,<20250513.0a0
+ - libcurl >=8.17.0,<9.0a0
+ - libgcc >=14
+ - libgrpc >=1.73.1,<1.74.0a0
+ - libjpeg-turbo >=3.1.2,<4.0a0
+ - libpng >=1.6.51,<1.7.0a0
+ - libprotobuf >=6.31.1,<6.31.2.0a0
+ - libsqlite >=3.51.1,<4.0a0
+ - libstdcxx >=14
+ - libtensorflow_cc 2.19.1 cpu_hf7abd0a_2
+ - libtensorflow_framework 2.19.1 cpu_h12ecb4a_2
+ - libzlib >=1.3.1,<2.0a0
+ - ml_dtypes >=0.5.1,<1.0
+ - numpy >=1.23,<3
+ - openssl >=3.5.4,<4.0a0
+ - opt_einsum >=2.3.2
+ - packaging
+ - protobuf >=5.26
+ - python >=3.12,<3.13.0a0
+ - python-flatbuffers >=24.3.25
+ - python_abi 3.12.* *_cp312
+ - requests >=2.21.0,<3
+ - six >=1.12
+ - snappy >=1.2.2,<1.3.0a0
+ - tensorboard >=2.19,<2.20
+ - termcolor >=1.1.0
+ - typing_extensions >=3.6.6
+ - wrapt >=1.11.0
+ track_features:
+ - tensorflow-cpu
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tensorflow?source=hash-mapping
+ size: 66247661
+ timestamp: 1764397531143
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorflow-base-2.18.0-cpu_py312h7226aab_2.conda
+ sha256: 9e5dd1df01161554df24f353e51725c9c23efcaed3b0eee58b6626fccefd0208
+ md5: e5018354e19820fafdf13916a3c17923
+ depends:
+ - absl-py >=1.0.0
+ - astunparse >=1.6.0
+ - flatbuffers >=24.12.23,<24.12.24.0a0
+ - gast >=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
+ - giflib >=5.2.2,<5.3.0a0
+ - google-pasta >=0.1.1
+ - grpcio 1.67.*
+ - h5py >=3.11
+ - icu >=75.1,<76.0a0
+ - keras >=3.0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcurl >=8.14.1,<9.0a0
+ - libgcc
+ - libgcc-ng >=12
+ - libgrpc >=1.67.1,<1.68.0a0
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - libpng >=1.6.50,<1.7.0a0
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libstdcxx
+ - libstdcxx-ng >=12
+ - libtensorflow_cc 2.18.0 cpu_h26186cf_2
+ - libtensorflow_framework 2.18.0 cpu_h78d15be_2
+ - libzlib >=1.3.1,<2.0a0
+ - ml_dtypes >=0.4.0,<0.5
+ - numpy >=1.23,<3
+ - openssl >=3.5.2,<4.0a0
+ - opt_einsum >=2.3.2
+ - packaging
+ - protobuf >=5.26,<6
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python-flatbuffers >=24.3.25
+ - python_abi 3.12.* *_cp312
+ - requests >=2.21.0,<3
+ - six >=1.12
+ - snappy >=1.2.2,<1.3.0a0
+ - tensorboard >=2.18,<2.19
+ - termcolor >=1.1.0
+ - typing_extensions >=3.6.6
+ - wrapt >=1.11.0
+ track_features:
+ - tensorflow-cpu
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tensorflow?source=hash-mapping
+ size: 80269877
+ timestamp: 1757538849849
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorflow-base-2.18.0-cpu_py312h81ab8d0_1.conda
+ sha256: a0e4bf6530a5e8f9efd2e8db5708a6664372aac866ebdd5987f5318b27fc8efa
+ md5: 0f4a1295b15d2797f8beaee0f22af723
+ depends:
+ - __osx >=11.0
+ - absl-py >=1.0.0
+ - astunparse >=1.6.0
+ - flatbuffers >=24.12.23,<24.12.24.0a0
+ - gast >=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
+ - giflib >=5.2.2,<5.3.0a0
+ - google-pasta >=0.1.1
+ - grpcio 1.67.*
+ - h5py >=3.11
+ - icu >=75.1,<76.0a0
+ - keras >=3.0
+ - libabseil * cxx17*
+ - libabseil >=20240722.0,<20240723.0a0
+ - libcurl >=8.14.1,<9.0a0
+ - libcxx >=18
+ - libgrpc >=1.67.1,<1.68.0a0
+ - libjpeg-turbo >=3.1.0,<4.0a0
+ - libpng >=1.6.50,<1.7.0a0
+ - libprotobuf >=5.28.3,<5.28.4.0a0
+ - libsqlite >=3.50.4,<4.0a0
+ - libtensorflow_cc 2.18.0 cpu_hf321e49_1
+ - libtensorflow_framework 2.18.0 cpu_h2398287_1
+ - libzlib >=1.3.1,<2.0a0
+ - ml_dtypes >=0.4.0,<0.5
+ - numpy >=1.23,<3
+ - openssl >=3.5.2,<4.0a0
+ - opt_einsum >=2.3.2
+ - packaging
+ - protobuf >=5.26,<6
+ - python >=3.12,<3.13.0a0
+ - python-flatbuffers >=24.3.25
+ - python_abi 3.12.* *_cp312
+ - requests >=2.21.0,<3
+ - six >=1.12
+ - snappy >=1.2.2,<1.3.0a0
+ - tensorboard >=2.18,<2.19
+ - termcolor >=1.1.0
+ - typing_extensions >=3.6.6
+ - wrapt >=1.11.0
+ track_features:
+ - tensorflow-cpu
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tensorflow?source=hash-mapping
+ size: 73631276
+ timestamp: 1754498401137
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tensorflow-estimator-2.19.1-cpu_py312h6e6b5e2_2.conda
+ sha256: a5eafae32d7b1f2753c9cefaf20b3798be5c6d13464c2de395618b1d2e5aaa01
+ md5: f0c5802e45cf651108db4862a64e10d4
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _x86_64-microarch-level >=1
+ - libgcc >=14
+ - libstdcxx >=14
+ - openssl >=3.5.4,<4.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tensorflow-base 2.19.1 cpu_py312h0afb428_2
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tensorflow-estimator?source=hash-mapping
+ size: 704088
+ timestamp: 1764398199860
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tensorflow-estimator-2.18.0-cpu_py312h15e21a2_2.conda
+ sha256: 58a48616a174f09574652c866f201afff5d87ba06715faf0239cda45eef32bbc
+ md5: 1b9eb5960bbfde7e90ffb9e789d362d6
+ depends:
+ - libgcc
+ - libgcc-ng >=12
+ - libstdcxx
+ - libstdcxx-ng >=12
+ - openssl >=3.5.2,<4.0a0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ - tensorflow-base 2.18.0 cpu_py312h7226aab_2
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tensorflow-estimator?source=hash-mapping
+ size: 696158
+ timestamp: 1757539978062
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tensorflow-estimator-2.18.0-cpu_py312h5e86b3d_1.conda
+ sha256: 0e91eb003237bb8279ce870fc12e7e21d1c04a39eb6d1cac116ec67fda23884d
+ md5: 65d1fbbbb27cad0fb2266cb0f612b9fc
+ depends:
+ - __osx >=11.0
+ - libcxx >=18
+ - openssl >=3.5.2,<4.0a0
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ - tensorflow-base 2.18.0 cpu_py312h81ab8d0_1
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tensorflow-estimator?source=hash-mapping
+ size: 699391
+ timestamp: 1754499167407
+- conda: https://conda.anaconda.org/conda-forge/noarch/termcolor-3.3.0-pyhd8ed1ab_0.conda
+ sha256: 2107f959cd2a8a804d52e124434088e1a28c843942b62a7f8a3d84072861f0ef
+ md5: bc6228906129e420c74a5ebaf0d63936
+ depends:
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/termcolor?source=hash-mapping
+ size: 13259
+ timestamp: 1767096412722
+- conda: https://conda.anaconda.org/conda-forge/noarch/tf2onnx-1.16.1-pyhd8ed1ab_1.conda
+ sha256: f9e706426d3fa4d704da90f3aedd5fe736e1afafa0b9aed16d46bbf9ea5370e4
+ md5: 80219f6eb6e6f6a17504979cbdde5217
+ depends:
+ - numpy >=1.14.1
+ - onnx >=1.4.1
+ - python >=3.9
+ - python-flatbuffers >=1.12
+ - requests
+ - six
+ - tensorflow >=2.6
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/tf2onnx?source=hash-mapping
+ size: 275501
+ timestamp: 1736587098584
+- conda: https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.6.0-pyhecae5ae_0.conda
+ sha256: 6016672e0e72c4cf23c0cf7b1986283bd86a9c17e8d319212d78d8e9ae42fdfd
+ md5: 9d64911b31d57ca443e9f1e36b04385f
+ depends:
+ - python >=3.9
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/threadpoolctl?source=hash-mapping
+ size: 23869
+ timestamp: 1741878358548
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda
+ sha256: 1544760538a40bcd8ace2b1d8ebe3eb5807ac268641f8acdc18c69c5ebfeaf64
+ md5: 86bc20552bf46075e3d92b67f089172d
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - xorg-libx11 >=1.8.12,<2.0a0
+ license: TCL
+ license_family: BSD
+ purls: []
+ size: 3284905
+ timestamp: 1763054914403
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h561c983_103.conda
+ sha256: 154e73f6269f92ad5257aa2039278b083998fd19d371e150f307483fb93c07ae
+ md5: 631db4799bc2bfe4daccf80bb3cbc433
+ depends:
+ - libgcc >=13
+ - libzlib >=1.3.1,<2.0a0
+ constrains:
+ - xorg-libx11 >=1.8.12,<2.0a0
+ license: TCL
+ license_family: BSD
+ purls: []
+ size: 3333495
+ timestamp: 1763059192223
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
+ sha256: ad0c67cb03c163a109820dc9ecf77faf6ec7150e942d1e8bb13e5d39dc058ab7
+ md5: a73d54a5abba6543cb2f0af1bfbd6851
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.1,<2.0a0
+ license: TCL
+ license_family: BSD
+ purls: []
+ size: 3125484
+ timestamp: 1763055028377
+- conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
+ sha256: fd30e43699cb22ab32ff3134d3acf12d6010b5bbaa63293c37076b50009b91f8
+ md5: d0fc809fa4c4d85e959ce4ab6e1de800
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/toml?source=hash-mapping
+ size: 24017
+ timestamp: 1764486833072
+- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
+ sha256: cb77c660b646c00a48ef942a9e1721ee46e90230c7c570cdeb5a893b5cce9bff
+ md5: d2732eb636c264dc9aa4cbee404b1a53
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/tomli?source=compressed-mapping
+ size: 20973
+ timestamp: 1760014679845
+- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
+ sha256: f8d3b49c084831a20923f66826f30ecfc55a4cd951e544b7213c692887343222
+ md5: 146402bf0f11cbeb8f781fa4309a95d3
+ depends:
+ - python >=3.9
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/tomlkit?source=hash-mapping
+ size: 38777
+ timestamp: 1749127286558
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.3-py312h4c3975b_0.conda
+ sha256: bed440cad040f0fe76266f9a527feecbaf00385b68a96532aa69614fe5153f8e
+ md5: e03a4bf52d2170d64c816b2a52972097
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tornado?source=compressed-mapping
+ size: 850918
+ timestamp: 1765458857375
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tornado-6.5.3-py312hefbd42c_0.conda
+ sha256: 876235b9c8e6ff91990ac9a1ca2041257e0854d47897394190a376473371e7fc
+ md5: b1ec9447183674b86aee6466fc98a840
+ depends:
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tornado?source=hash-mapping
+ size: 853090
+ timestamp: 1765460044183
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.4-py312h4409184_0.conda
+ sha256: 114bfa1b859a64c589c428fce0ff8e358d8f0aaa7b98d353b94a95c7bceae640
+ md5: fde4548a1e99c14eea9752f270ab68aa
+ depends:
+ - __osx >=11.0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/tornado?source=hash-mapping
+ size: 854598
+ timestamp: 1765836762571
+- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_1.conda
+ sha256: 11e2c85468ae9902d24a27137b6b39b4a78099806e551d390e394a8c34b48e40
+ md5: 9efbfdc37242619130ea42b1cc4ed861
+ depends:
+ - colorama
+ - python >=3.9
+ license: MPL-2.0 or MIT
+ purls:
+ - pkg:pypi/tqdm?source=hash-mapping
+ size: 89498
+ timestamp: 1735661472632
+- conda: https://conda.anaconda.org/conda-forge/noarch/typer-0.21.0-pyhbb89825_0.conda
+ sha256: 450fee86790935c6f2bd0f96e8ebdada35ea94c7b6851c300811d7dfda5717d2
+ md5: 053a45ad64fe08064eff395e4532673f
+ depends:
+ - typer-slim-standard ==0.21.0 hd63da06_0
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/typer?source=hash-mapping
+ size: 78226
+ timestamp: 1766678933770
+- conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-0.21.0-pyhcf101f3_0.conda
+ sha256: ad6f22f7eeb59ff83c50631592772a3c2183dd211d34ed68f5145dafb0faae60
+ md5: 1bf7599d9f131a06288a2173284b1e4f
+ depends:
+ - python >=3.10
+ - click >=8.0.0
+ - typing_extensions >=3.7.4.3
+ - python
+ constrains:
+ - typer 0.21.0.*
+ - rich >=10.11.0
+ - shellingham >=1.3.0
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/typer-slim?source=hash-mapping
+ size: 47958
+ timestamp: 1766678933764
+- conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.21.0-hd63da06_0.conda
+ sha256: 031512e8d54fc03a1efc7d725c840401de1eeaa3fef00888d864fbfc31a0e6c1
+ md5: b9b9911609c8371886a79e8fdccaff0f
+ depends:
+ - typer-slim ==0.21.0 pyhcf101f3_0
+ - rich
+ - shellingham
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 5325
+ timestamp: 1766678933769
+- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda
+ sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c
+ md5: edd329d7d3a4ab45dcf905899a7a6115
+ depends:
+ - typing_extensions ==4.15.0 pyhcf101f3_0
+ license: PSF-2.0
+ license_family: PSF
+ purls: []
+ size: 91383
+ timestamp: 1756220668932
+- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
+ sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731
+ md5: 0caa1af407ecff61170c9437a808404d
+ depends:
+ - python >=3.10
+ - python
+ license: PSF-2.0
+ license_family: PSF
+ purls:
+ - pkg:pypi/typing-extensions?source=hash-mapping
+ size: 51692
+ timestamp: 1756220668932
+- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda
+ sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c
+ md5: ad659d0a2b3e47e38d829aa8cad2d610
+ license: LicenseRef-Public-Domain
+ purls: []
+ size: 119135
+ timestamp: 1767016325805
+- conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.0-py312h4c3975b_1.conda
+ sha256: 3c812c634e78cec74e224cc6adf33aed533d9fe1ee1eff7f692e1f338efb8c5b
+ md5: a0b8efbe73c90f810a171a6c746be087
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/unicodedata2?source=hash-mapping
+ size: 408399
+ timestamp: 1763054875733
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/unicodedata2-17.0.0-py312hcd1a082_1.conda
+ sha256: c85105d976dba34606c528698e50a518d68ac7113191e590b0546d0df8d10253
+ md5: 24e0209609c4372af491052b6c637b2e
+ depends:
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/unicodedata2?source=hash-mapping
+ size: 408819
+ timestamp: 1763055001055
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/unicodedata2-17.0.0-py312h4409184_1.conda
+ sha256: 567cebbb3a1a5c76e5ec43508e01ccbe98923ad0003eafd87acbbc546fcd588c
+ md5: b0b0c7ea4888b6f4009afa7001e6adaa
+ depends:
+ - __osx >=11.0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: Apache-2.0
+ license_family: Apache
+ purls:
+ - pkg:pypi/unicodedata2?source=hash-mapping
+ size: 416271
+ timestamp: 1763055285615
+- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.2-pyhd8ed1ab_0.conda
+ sha256: f4302a80ee9b76279ad061df05003abc2a29cc89751ffab2fd2919b43455dac0
+ md5: 4949ca7b83065cfe94ebe320aece8c72
+ 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=compressed-mapping
+ size: 102842
+ timestamp: 1765719817255
+- conda: https://conda.anaconda.org/conda-forge/linux-64/wayland-1.24.0-hd6090a7_1.conda
+ sha256: 3aa04ae8e9521d9b56b562376d944c3e52b69f9d2a0667f77b8953464822e125
+ md5: 035da2e4f5770f036ff704fa17aace24
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libexpat >=2.7.1,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - libstdcxx >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 329779
+ timestamp: 1761174273487
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wayland-1.24.0-h4f8a99f_1.conda
+ sha256: d94af8f287db764327ac7b48f6c0cd5c40da6ea2606afd34ac30671b7c85d8ee
+ md5: f6966cb1f000c230359ae98c29e37d87
+ depends:
+ - libexpat >=2.7.1,<3.0a0
+ - libffi >=3.5.2,<3.6.0a0
+ - libgcc >=14
+ - libstdcxx >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 331480
+ timestamp: 1761174368396
+- conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.4-pyhcf101f3_0.conda
+ sha256: 0c4a30a4713347ff822d73d2349fd9ef67a6f34993e7ae3434cdee7047e9ee1e
+ md5: de082192dffe45d19aff3d86a4d06a24
+ depends:
+ - markupsafe >=2.1.1
+ - python >=3.10
+ - python
+ license: BSD-3-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/werkzeug?source=hash-mapping
+ size: 256621
+ timestamp: 1764423417723
+- conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-2.0.1-py312h4c3975b_1.conda
+ sha256: d1d352da699a642be0fd7a5cc894c37b1e8ddfda37c723cacfa9b1986824f80d
+ md5: b6ee834617873da8a2196c109275b38b
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python_abi 3.12.* *_cp312
+ license: BSD-2-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/wrapt?source=hash-mapping
+ size: 86544
+ timestamp: 1762594992655
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/wrapt-2.0.1-py312hcd1a082_1.conda
+ sha256: 699f0ee266dec6be39128889a2750d844aefc71cdc7e86b073e97c535d392234
+ md5: 8eac3fe905f9e86817066b16050ea5e5
+ depends:
+ - libgcc >=14
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: BSD-2-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/wrapt?source=hash-mapping
+ size: 86948
+ timestamp: 1762595183841
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-2.0.1-py312h4409184_1.conda
+ sha256: 53b97d650332321e67e046de2c29ff60bc742a17d5e4c48a15c704933843e156
+ md5: 2b3afb010681e2dcfbf27366d373f5c8
+ depends:
+ - __osx >=11.0
+ - python >=3.12,<3.13.0a0
+ - python >=3.12,<3.13.0a0 *_cpython
+ - python_abi 3.12.* *_cp312
+ license: BSD-2-Clause
+ license_family: BSD
+ purls:
+ - pkg:pypi/wrapt?source=hash-mapping
+ size: 83380
+ timestamp: 1762595281305
+- 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: []
- size: 313930
- timestamp: 1765813902568
-- pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl
- name: requests
- version: 2.32.5
- sha256: 2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6
- requires_dist:
- - charset-normalizer>=2,<4
- - idna>=2.5,<4
- - urllib3>=1.21.1,<3
- - certifi>=2017.4.17
- - pysocks>=1.5.6,!=1.5.7 ; extra == 'socks'
- - chardet>=3.0.2,<6 ; extra == 'use-chardet-on-py3'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl
- name: rich
- version: 14.2.0
- sha256: 76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd
- requires_dist:
- - ipywidgets>=7.5.1,<9 ; extra == 'jupyter'
- - markdown-it-py>=2.2.0
- - pygments>=2.13.0,<3.0.0
- requires_python: '>=3.8.0'
-- pypi: https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- name: scikit-learn
- version: 1.8.0
- sha256: 74b66d8689d52ed04c271e1329f0c61635bcaf5b926db9b12d58914cdc01fe57
- requires_dist:
- - numpy>=1.24.1
- - scipy>=1.10.0
- - joblib>=1.3.0
- - threadpoolctl>=3.2.0
- - numpy>=1.24.1 ; extra == 'build'
- - scipy>=1.10.0 ; extra == 'build'
- - cython>=3.1.2 ; extra == 'build'
- - meson-python>=0.17.1 ; extra == 'build'
- - numpy>=1.24.1 ; extra == 'install'
- - scipy>=1.10.0 ; extra == 'install'
- - joblib>=1.3.0 ; extra == 'install'
- - threadpoolctl>=3.2.0 ; extra == 'install'
- - matplotlib>=3.6.1 ; extra == 'benchmark'
- - pandas>=1.5.0 ; extra == 'benchmark'
- - memory-profiler>=0.57.0 ; extra == 'benchmark'
- - matplotlib>=3.6.1 ; extra == 'docs'
- - scikit-image>=0.22.0 ; extra == 'docs'
- - pandas>=1.5.0 ; extra == 'docs'
- - seaborn>=0.13.0 ; extra == 'docs'
- - memory-profiler>=0.57.0 ; extra == 'docs'
- - sphinx>=7.3.7 ; extra == 'docs'
- - sphinx-copybutton>=0.5.2 ; extra == 'docs'
- - sphinx-gallery>=0.17.1 ; extra == 'docs'
- - numpydoc>=1.2.0 ; extra == 'docs'
- - pillow>=10.1.0 ; extra == 'docs'
- - pooch>=1.8.0 ; extra == 'docs'
- - sphinx-prompt>=1.4.0 ; extra == 'docs'
- - sphinxext-opengraph>=0.9.1 ; extra == 'docs'
- - plotly>=5.18.0 ; extra == 'docs'
- - polars>=0.20.30 ; extra == 'docs'
- - sphinx-design>=0.6.0 ; extra == 'docs'
- - sphinxcontrib-sass>=0.3.4 ; extra == 'docs'
- - pydata-sphinx-theme>=0.15.3 ; extra == 'docs'
- - sphinx-remove-toctrees>=1.0.0.post1 ; extra == 'docs'
- - towncrier>=24.8.0 ; extra == 'docs'
- - matplotlib>=3.6.1 ; extra == 'examples'
- - scikit-image>=0.22.0 ; extra == 'examples'
- - pandas>=1.5.0 ; extra == 'examples'
- - seaborn>=0.13.0 ; extra == 'examples'
- - pooch>=1.8.0 ; extra == 'examples'
- - plotly>=5.18.0 ; extra == 'examples'
- - matplotlib>=3.6.1 ; extra == 'tests'
- - pandas>=1.5.0 ; extra == 'tests'
- - pytest>=7.1.2 ; extra == 'tests'
- - pytest-cov>=2.9.0 ; extra == 'tests'
- - ruff>=0.11.7 ; extra == 'tests'
- - mypy>=1.15 ; extra == 'tests'
- - pyamg>=5.0.0 ; extra == 'tests'
- - polars>=0.20.30 ; extra == 'tests'
- - pyarrow>=12.0.0 ; extra == 'tests'
- - numpydoc>=1.2.0 ; extra == 'tests'
- - pooch>=1.8.0 ; extra == 'tests'
- - conda-lock==3.0.1 ; extra == 'maintenance'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- name: scikit-learn
- version: 1.8.0
- sha256: 8fdf95767f989b0cfedb85f7ed8ca215d4be728031f56ff5a519ee1e3276dc2e
- requires_dist:
- - numpy>=1.24.1
- - scipy>=1.10.0
- - joblib>=1.3.0
- - threadpoolctl>=3.2.0
- - numpy>=1.24.1 ; extra == 'build'
- - scipy>=1.10.0 ; extra == 'build'
- - cython>=3.1.2 ; extra == 'build'
- - meson-python>=0.17.1 ; extra == 'build'
- - numpy>=1.24.1 ; extra == 'install'
- - scipy>=1.10.0 ; extra == 'install'
- - joblib>=1.3.0 ; extra == 'install'
- - threadpoolctl>=3.2.0 ; extra == 'install'
- - matplotlib>=3.6.1 ; extra == 'benchmark'
- - pandas>=1.5.0 ; extra == 'benchmark'
- - memory-profiler>=0.57.0 ; extra == 'benchmark'
- - matplotlib>=3.6.1 ; extra == 'docs'
- - scikit-image>=0.22.0 ; extra == 'docs'
- - pandas>=1.5.0 ; extra == 'docs'
- - seaborn>=0.13.0 ; extra == 'docs'
- - memory-profiler>=0.57.0 ; extra == 'docs'
- - sphinx>=7.3.7 ; extra == 'docs'
- - sphinx-copybutton>=0.5.2 ; extra == 'docs'
- - sphinx-gallery>=0.17.1 ; extra == 'docs'
- - numpydoc>=1.2.0 ; extra == 'docs'
- - pillow>=10.1.0 ; extra == 'docs'
- - pooch>=1.8.0 ; extra == 'docs'
- - sphinx-prompt>=1.4.0 ; extra == 'docs'
- - sphinxext-opengraph>=0.9.1 ; extra == 'docs'
- - plotly>=5.18.0 ; extra == 'docs'
- - polars>=0.20.30 ; extra == 'docs'
- - sphinx-design>=0.6.0 ; extra == 'docs'
- - sphinxcontrib-sass>=0.3.4 ; extra == 'docs'
- - pydata-sphinx-theme>=0.15.3 ; extra == 'docs'
- - sphinx-remove-toctrees>=1.0.0.post1 ; extra == 'docs'
- - towncrier>=24.8.0 ; extra == 'docs'
- - matplotlib>=3.6.1 ; extra == 'examples'
- - scikit-image>=0.22.0 ; extra == 'examples'
- - pandas>=1.5.0 ; extra == 'examples'
- - seaborn>=0.13.0 ; extra == 'examples'
- - pooch>=1.8.0 ; extra == 'examples'
- - plotly>=5.18.0 ; extra == 'examples'
- - matplotlib>=3.6.1 ; extra == 'tests'
- - pandas>=1.5.0 ; extra == 'tests'
- - pytest>=7.1.2 ; extra == 'tests'
- - pytest-cov>=2.9.0 ; extra == 'tests'
- - ruff>=0.11.7 ; extra == 'tests'
- - mypy>=1.15 ; extra == 'tests'
- - pyamg>=5.0.0 ; extra == 'tests'
- - polars>=0.20.30 ; extra == 'tests'
- - pyarrow>=12.0.0 ; extra == 'tests'
- - numpydoc>=1.2.0 ; extra == 'tests'
- - pooch>=1.8.0 ; extra == 'tests'
- - conda-lock==3.0.1 ; extra == 'maintenance'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl
- name: scikit-learn
- version: 1.8.0
- sha256: edec98c5e7c128328124a029bceb09eda2d526997780fef8d65e9a69eead963e
- requires_dist:
- - numpy>=1.24.1
- - scipy>=1.10.0
- - joblib>=1.3.0
- - threadpoolctl>=3.2.0
- - numpy>=1.24.1 ; extra == 'build'
- - scipy>=1.10.0 ; extra == 'build'
- - cython>=3.1.2 ; extra == 'build'
- - meson-python>=0.17.1 ; extra == 'build'
- - numpy>=1.24.1 ; extra == 'install'
- - scipy>=1.10.0 ; extra == 'install'
- - joblib>=1.3.0 ; extra == 'install'
- - threadpoolctl>=3.2.0 ; extra == 'install'
- - matplotlib>=3.6.1 ; extra == 'benchmark'
- - pandas>=1.5.0 ; extra == 'benchmark'
- - memory-profiler>=0.57.0 ; extra == 'benchmark'
- - matplotlib>=3.6.1 ; extra == 'docs'
- - scikit-image>=0.22.0 ; extra == 'docs'
- - pandas>=1.5.0 ; extra == 'docs'
- - seaborn>=0.13.0 ; extra == 'docs'
- - memory-profiler>=0.57.0 ; extra == 'docs'
- - sphinx>=7.3.7 ; extra == 'docs'
- - sphinx-copybutton>=0.5.2 ; extra == 'docs'
- - sphinx-gallery>=0.17.1 ; extra == 'docs'
- - numpydoc>=1.2.0 ; extra == 'docs'
- - pillow>=10.1.0 ; extra == 'docs'
- - pooch>=1.8.0 ; extra == 'docs'
- - sphinx-prompt>=1.4.0 ; extra == 'docs'
- - sphinxext-opengraph>=0.9.1 ; extra == 'docs'
- - plotly>=5.18.0 ; extra == 'docs'
- - polars>=0.20.30 ; extra == 'docs'
- - sphinx-design>=0.6.0 ; extra == 'docs'
- - sphinxcontrib-sass>=0.3.4 ; extra == 'docs'
- - pydata-sphinx-theme>=0.15.3 ; extra == 'docs'
- - sphinx-remove-toctrees>=1.0.0.post1 ; extra == 'docs'
- - towncrier>=24.8.0 ; extra == 'docs'
- - matplotlib>=3.6.1 ; extra == 'examples'
- - scikit-image>=0.22.0 ; extra == 'examples'
- - pandas>=1.5.0 ; extra == 'examples'
- - seaborn>=0.13.0 ; extra == 'examples'
- - pooch>=1.8.0 ; extra == 'examples'
- - plotly>=5.18.0 ; extra == 'examples'
- - matplotlib>=3.6.1 ; extra == 'tests'
- - pandas>=1.5.0 ; extra == 'tests'
- - pytest>=7.1.2 ; extra == 'tests'
- - pytest-cov>=2.9.0 ; extra == 'tests'
- - ruff>=0.11.7 ; extra == 'tests'
- - mypy>=1.15 ; extra == 'tests'
- - pyamg>=5.0.0 ; extra == 'tests'
- - polars>=0.20.30 ; extra == 'tests'
- - pyarrow>=12.0.0 ; extra == 'tests'
- - numpydoc>=1.2.0 ; extra == 'tests'
- - pooch>=1.8.0 ; extra == 'tests'
- - conda-lock==3.0.1 ; extra == 'maintenance'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- name: scipy
- version: 1.16.3
- sha256: 7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88
- requires_dist:
- - numpy>=1.25.2,<2.6
- - 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'
- - 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'
- - mypy==1.10.0 ; extra == 'dev'
- - typing-extensions ; extra == 'dev'
- - types-psutil ; extra == 'dev'
- - pycodestyle ; extra == 'dev'
- - ruff>=0.0.292 ; extra == 'dev'
- - cython-lint>=0.12.2 ; extra == 'dev'
- - rich-click ; extra == 'dev'
- - doit>=0.36.0 ; extra == 'dev'
- - pydevtool ; extra == 'dev'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl
- name: scipy
- version: 1.16.3
- sha256: 16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d
- requires_dist:
- - numpy>=1.25.2,<2.6
- - 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'
- - 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'
- - mypy==1.10.0 ; extra == 'dev'
- - typing-extensions ; extra == 'dev'
- - types-psutil ; extra == 'dev'
- - pycodestyle ; extra == 'dev'
- - ruff>=0.0.292 ; extra == 'dev'
- - cython-lint>=0.12.2 ; extra == 'dev'
- - rich-click ; extra == 'dev'
- - doit>=0.36.0 ; extra == 'dev'
- - pydevtool ; extra == 'dev'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- name: scipy
- version: 1.16.3
- sha256: 0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959
- requires_dist:
- - numpy>=1.25.2,<2.6
- - 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'
- - 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'
- - mypy==1.10.0 ; extra == 'dev'
- - typing-extensions ; extra == 'dev'
- - types-psutil ; extra == 'dev'
- - pycodestyle ; extra == 'dev'
- - ruff>=0.0.292 ; extra == 'dev'
- - cython-lint>=0.12.2 ; extra == 'dev'
- - rich-click ; extra == 'dev'
- - doit>=0.36.0 ; extra == 'dev'
- - pydevtool ; extra == 'dev'
- requires_python: '>=3.11'
-- pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl
- name: setuptools
- version: 80.9.0
- sha256: 062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922
- 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'
- - platformdirs>=4.2.2 ; extra == 'core'
- - jaraco-functools>=4 ; extra == 'core'
- - more-itertools ; extra == 'core'
- - pytest-checkdocs>=2.4 ; extra == 'check'
- - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check'
- - ruff>=0.8.0 ; sys_platform != 'cygwin' and extra == 'check'
- - pytest-cov ; extra == 'cover'
- - pytest-enabler>=2.2 ; extra == 'enabler'
- - pytest-mypy ; extra == 'type'
- - mypy==1.14.* ; 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.9'
-- pypi: https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl
- name: shellingham
- version: 1.5.4
- sha256: 7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/09/1d/171009bd35c7099d72ef6afd4bb13527bab469965c968a17d69a203d62a6/simplejson-3.20.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- name: simplejson
- version: 3.20.2
- sha256: 552f55745044a24c3cb7ec67e54234be56d5d6d0e054f2e4cf4fb3e297429be5
- requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
-- pypi: https://files.pythonhosted.org/packages/43/f1/b392952200f3393bb06fbc4dd975fc63a6843261705839355560b7264eb2/simplejson-3.20.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- name: simplejson
- version: 3.20.2
- sha256: 133ae2098a8e162c71da97cdab1f383afdd91373b7ff5fe65169b04167da976b
- requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
-- pypi: https://files.pythonhosted.org/packages/7a/4d/30dfef83b9ac48afae1cf1ab19c2867e27b8d22b5d9f8ca7ce5a0a157d8c/simplejson-3.20.2-cp313-cp313-macosx_11_0_arm64.whl
- name: simplejson
- version: 3.20.2
- sha256: 6b1d8d7c3e1a205c49e1aee6ba907dcb8ccea83651e6c3e2cb2062f1e52b0726
- requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*'
-- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- name: six
- version: 1.17.0
- sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
- requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
-- pypi: https://files.pythonhosted.org/packages/57/ec/9a0d709217aa385d87b3eadcf19e2ae32eca097077fa2236312d5fc8f656/skl2onnx-1.19.1-py3-none-any.whl
- name: skl2onnx
- version: 1.19.1
- sha256: fddf2f49e3ffc355f332e676b43c6fec5e63797627925b279d9f5b2c4d0c81a7
- requires_dist:
- - onnx>=1.2.1
- - scikit-learn>=1.1
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- name: sqlalchemy
- version: 2.0.45
- sha256: 672c45cae53ba88e0dad74b9027dddd09ef6f441e927786b05bec75d949fbb2e
- requires_dist:
- - importlib-metadata ; python_full_version < '3.8'
- - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'
- - typing-extensions>=4.6.0
- - greenlet>=1 ; extra == 'asyncio'
- - mypy>=0.910 ; extra == 'mypy'
- - pyodbc ; extra == 'mssql'
- - pymssql ; extra == 'mssql-pymssql'
- - pyodbc ; extra == 'mssql-pyodbc'
- - mysqlclient>=1.4.0 ; extra == 'mysql'
- - mysql-connector-python ; extra == 'mysql-connector'
- - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector'
- - cx-oracle>=8 ; extra == 'oracle'
- - oracledb>=1.0.1 ; extra == 'oracle-oracledb'
- - psycopg2>=2.7 ; extra == 'postgresql'
- - pg8000>=1.29.1 ; extra == 'postgresql-pg8000'
- - greenlet>=1 ; extra == 'postgresql-asyncpg'
- - asyncpg ; extra == 'postgresql-asyncpg'
- - psycopg2-binary ; extra == 'postgresql-psycopg2binary'
- - psycopg2cffi ; extra == 'postgresql-psycopg2cffi'
- - psycopg>=3.0.7 ; extra == 'postgresql-psycopg'
- - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary'
- - pymysql ; extra == 'pymysql'
- - greenlet>=1 ; extra == 'aiomysql'
- - aiomysql>=0.2.0 ; extra == 'aiomysql'
- - greenlet>=1 ; extra == 'aioodbc'
- - aioodbc ; extra == 'aioodbc'
- - greenlet>=1 ; extra == 'asyncmy'
- - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy'
- - greenlet>=1 ; extra == 'aiosqlite'
- - aiosqlite ; extra == 'aiosqlite'
- - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
- - sqlcipher3-binary ; extra == 'sqlcipher'
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: sqlalchemy
- version: 2.0.45
- sha256: fe187fc31a54d7fd90352f34e8c008cf3ad5d064d08fedd3de2e8df83eb4a1cf
- requires_dist:
- - importlib-metadata ; python_full_version < '3.8'
- - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'
- - typing-extensions>=4.6.0
- - greenlet>=1 ; extra == 'asyncio'
- - mypy>=0.910 ; extra == 'mypy'
- - pyodbc ; extra == 'mssql'
- - pymssql ; extra == 'mssql-pymssql'
- - pyodbc ; extra == 'mssql-pyodbc'
- - mysqlclient>=1.4.0 ; extra == 'mysql'
- - mysql-connector-python ; extra == 'mysql-connector'
- - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector'
- - cx-oracle>=8 ; extra == 'oracle'
- - oracledb>=1.0.1 ; extra == 'oracle-oracledb'
- - psycopg2>=2.7 ; extra == 'postgresql'
- - pg8000>=1.29.1 ; extra == 'postgresql-pg8000'
- - greenlet>=1 ; extra == 'postgresql-asyncpg'
- - asyncpg ; extra == 'postgresql-asyncpg'
- - psycopg2-binary ; extra == 'postgresql-psycopg2binary'
- - psycopg2cffi ; extra == 'postgresql-psycopg2cffi'
- - psycopg>=3.0.7 ; extra == 'postgresql-psycopg'
- - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary'
- - pymysql ; extra == 'pymysql'
- - greenlet>=1 ; extra == 'aiomysql'
- - aiomysql>=0.2.0 ; extra == 'aiomysql'
- - greenlet>=1 ; extra == 'aioodbc'
- - aioodbc ; extra == 'aioodbc'
- - greenlet>=1 ; extra == 'asyncmy'
- - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy'
- - greenlet>=1 ; extra == 'aiosqlite'
- - aiosqlite ; extra == 'aiosqlite'
- - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
- - sqlcipher3-binary ; extra == 'sqlcipher'
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl
- name: sqlalchemy
- version: 2.0.45
- sha256: 5225a288e4c8cc2308dbdd874edad6e7d0fd38eac1e9e5f23503425c8eee20d0
- requires_dist:
- - importlib-metadata ; python_full_version < '3.8'
- - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'
- - typing-extensions>=4.6.0
- - greenlet>=1 ; extra == 'asyncio'
- - mypy>=0.910 ; extra == 'mypy'
- - pyodbc ; extra == 'mssql'
- - pymssql ; extra == 'mssql-pymssql'
- - pyodbc ; extra == 'mssql-pyodbc'
- - mysqlclient>=1.4.0 ; extra == 'mysql'
- - mysql-connector-python ; extra == 'mysql-connector'
- - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector'
- - cx-oracle>=8 ; extra == 'oracle'
- - oracledb>=1.0.1 ; extra == 'oracle-oracledb'
- - psycopg2>=2.7 ; extra == 'postgresql'
- - pg8000>=1.29.1 ; extra == 'postgresql-pg8000'
- - greenlet>=1 ; extra == 'postgresql-asyncpg'
- - asyncpg ; extra == 'postgresql-asyncpg'
- - psycopg2-binary ; extra == 'postgresql-psycopg2binary'
- - psycopg2cffi ; extra == 'postgresql-psycopg2cffi'
- - psycopg>=3.0.7 ; extra == 'postgresql-psycopg'
- - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary'
- - pymysql ; extra == 'pymysql'
- - greenlet>=1 ; extra == 'aiomysql'
- - aiomysql>=0.2.0 ; extra == 'aiomysql'
- - greenlet>=1 ; extra == 'aioodbc'
- - aioodbc ; extra == 'aioodbc'
- - greenlet>=1 ; extra == 'asyncmy'
- - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy'
- - greenlet>=1 ; extra == 'aiosqlite'
- - aiosqlite ; extra == 'aiosqlite'
- - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite'
- - sqlcipher3-binary ; extra == 'sqlcipher'
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- name: statsmodels
- version: 0.14.6
- sha256: 730f3297b26749b216a06e4327fe0be59b8d05f7d594fb6caff4287b69654589
- requires_dist:
- - numpy>=1.22.3,<3
- - scipy>=1.8,!=1.9.2
- - pandas>=1.4,!=2.1.0
- - patsy>=0.5.6
- - packaging>=21.3
- - cython>=3.0.10 ; extra == 'build'
- - cython>=3.0.10 ; extra == 'develop'
- - cython>=3.0.10,<4 ; extra == 'develop'
- - setuptools-scm[toml]~=8.0 ; extra == 'develop'
- - matplotlib>=3 ; extra == 'develop'
- - colorama ; extra == 'develop'
- - joblib ; extra == 'develop'
- - jinja2 ; extra == 'develop'
- - pytest>=7.3.0,<8 ; extra == 'develop'
- - pytest-randomly ; extra == 'develop'
- - pytest-xdist ; extra == 'develop'
- - pytest-cov ; extra == 'develop'
- - pywinpty ; os_name == 'nt' and extra == 'develop'
- - flake8 ; extra == 'develop'
- - isort ; extra == 'develop'
- - sphinx ; extra == 'docs'
- - nbconvert ; extra == 'docs'
- - jupyter-client ; extra == 'docs'
- - ipykernel ; extra == 'docs'
- - matplotlib ; extra == 'docs'
- - nbformat ; extra == 'docs'
- - numpydoc ; extra == 'docs'
- - pandas-datareader ; extra == 'docs'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl
- name: statsmodels
- version: 0.14.6
- sha256: aa60d82e29fcd0a736e86feb63a11d2380322d77a9369a54be8b0965a3985f71
- requires_dist:
- - numpy>=1.22.3,<3
- - scipy>=1.8,!=1.9.2
- - pandas>=1.4,!=2.1.0
- - patsy>=0.5.6
- - packaging>=21.3
- - cython>=3.0.10 ; extra == 'build'
- - cython>=3.0.10 ; extra == 'develop'
- - cython>=3.0.10,<4 ; extra == 'develop'
- - setuptools-scm[toml]~=8.0 ; extra == 'develop'
- - matplotlib>=3 ; extra == 'develop'
- - colorama ; extra == 'develop'
- - joblib ; extra == 'develop'
- - jinja2 ; extra == 'develop'
- - pytest>=7.3.0,<8 ; extra == 'develop'
- - pytest-randomly ; extra == 'develop'
- - pytest-xdist ; extra == 'develop'
- - pytest-cov ; extra == 'develop'
- - pywinpty ; os_name == 'nt' and extra == 'develop'
- - flake8 ; extra == 'develop'
- - isort ; extra == 'develop'
- - sphinx ; extra == 'docs'
- - nbconvert ; extra == 'docs'
- - jupyter-client ; extra == 'docs'
- - ipykernel ; extra == 'docs'
- - matplotlib ; extra == 'docs'
- - nbformat ; extra == 'docs'
- - numpydoc ; extra == 'docs'
- - pandas-datareader ; extra == 'docs'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: statsmodels
- version: 0.14.6
- sha256: 89ee7d595f5939cc20bf946faedcb5137d975f03ae080f300ebb4398f16a5bd4
- requires_dist:
- - numpy>=1.22.3,<3
- - scipy>=1.8,!=1.9.2
- - pandas>=1.4,!=2.1.0
- - patsy>=0.5.6
- - packaging>=21.3
- - cython>=3.0.10 ; extra == 'build'
- - cython>=3.0.10 ; extra == 'develop'
- - cython>=3.0.10,<4 ; extra == 'develop'
- - setuptools-scm[toml]~=8.0 ; extra == 'develop'
- - matplotlib>=3 ; extra == 'develop'
- - colorama ; extra == 'develop'
- - joblib ; extra == 'develop'
- - jinja2 ; extra == 'develop'
- - pytest>=7.3.0,<8 ; extra == 'develop'
- - pytest-randomly ; extra == 'develop'
- - pytest-xdist ; extra == 'develop'
- - pytest-cov ; extra == 'develop'
- - pywinpty ; os_name == 'nt' and extra == 'develop'
- - flake8 ; extra == 'develop'
- - isort ; extra == 'develop'
- - sphinx ; extra == 'docs'
- - nbconvert ; extra == 'docs'
- - jupyter-client ; extra == 'docs'
- - ipykernel ; extra == 'docs'
- - matplotlib ; extra == 'docs'
- - nbformat ; extra == 'docs'
- - numpydoc ; extra == 'docs'
- - pandas-datareader ; extra == 'docs'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl
- name: sympy
- version: 1.14.0
- sha256: e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5
- requires_dist:
- - mpmath>=1.1.0,<1.4
- - pytest>=7.1.0 ; extra == 'dev'
- - hypothesis>=6.70.0 ; extra == 'dev'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/9c/d9/a5db55f88f258ac669a92858b70a714bbbd5acd993820b41ec4a96a4d77f/tensorboard-2.20.0-py3-none-any.whl
- name: tensorboard
- version: 2.20.0
- sha256: 9dc9f978cb84c0723acf9a345d96c184f0293d18f166bb8d59ee098e6cfaaba6
- requires_dist:
- - absl-py>=0.4
- - grpcio>=1.48.2
- - markdown>=2.6.8
- - numpy>=1.12.0
- - packaging
- - pillow
- - protobuf>=3.19.6,!=4.24.0
- - setuptools>=41.0.0
- - tensorboard-data-server>=0.7.0,<0.8.0
- - werkzeug>=1.0.1
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl
- name: tensorboard-data-server
- version: 0.7.2
- sha256: 7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/04/82/af283f402f8d1e9315644a331a5f0f326264c5d1de08262f3de5a5ade422/tensorflow-2.20.0-cp313-cp313-macosx_12_0_arm64.whl
- name: tensorflow
- version: 2.20.0
- sha256: 197f0b613b38c0da5c6a12a8295ad4a05c78b853835dae8e0f9dfae3ce9ce8a5
- requires_dist:
- - absl-py>=1.0.0
- - astunparse>=1.6.0
- - flatbuffers>=24.3.25
- - gast>=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
- - google-pasta>=0.1.1
- - libclang>=13.0.0
- - opt-einsum>=2.3.2
- - packaging
- - protobuf>=5.28.0
- - requests>=2.21.0,<3
- - setuptools
- - six>=1.12.0
- - termcolor>=1.1.0
- - typing-extensions>=3.6.6
- - wrapt>=1.11.0
- - grpcio>=1.24.3,<2.0
- - tensorboard~=2.20.0
- - keras>=3.10.0
- - numpy>=1.26.0
- - h5py>=3.11.0
- - ml-dtypes>=0.5.1,<1.0.0
- - nvidia-cublas-cu12>=12.5.3.2,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-cupti-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-nvcc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-nvrtc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-runtime-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cudnn-cu12>=9.3.0.75,<10.0 ; extra == 'and-cuda'
- - nvidia-cufft-cu12>=11.2.3.61,<12.0 ; extra == 'and-cuda'
- - nvidia-curand-cu12>=10.3.6.82,<11.0 ; extra == 'and-cuda'
- - nvidia-cusolver-cu12>=11.6.3.83,<12.0 ; extra == 'and-cuda'
- - nvidia-cusparse-cu12>=12.5.1.3,<13.0 ; extra == 'and-cuda'
- - nvidia-nccl-cu12>=2.25.1,<3.0 ; extra == 'and-cuda'
- - nvidia-nvjitlink-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
- - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/43/fb/8be8547c128613d82a2b006004026d86ed0bd672e913029a98153af4ffab/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- name: tensorflow
- version: 2.20.0
- sha256: 5fa3729b0126f75a99882b89fb7d536515721eda8014a63e259e780ba0a37372
- requires_dist:
- - absl-py>=1.0.0
- - astunparse>=1.6.0
- - flatbuffers>=24.3.25
- - gast>=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
- - google-pasta>=0.1.1
- - libclang>=13.0.0
- - opt-einsum>=2.3.2
- - packaging
- - protobuf>=5.28.0
- - requests>=2.21.0,<3
- - setuptools
- - six>=1.12.0
- - termcolor>=1.1.0
- - typing-extensions>=3.6.6
- - wrapt>=1.11.0
- - grpcio>=1.24.3,<2.0
- - tensorboard~=2.20.0
- - keras>=3.10.0
- - numpy>=1.26.0
- - h5py>=3.11.0
- - ml-dtypes>=0.5.1,<1.0.0
- - nvidia-cublas-cu12>=12.5.3.2,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-cupti-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-nvcc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-nvrtc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-runtime-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cudnn-cu12>=9.3.0.75,<10.0 ; extra == 'and-cuda'
- - nvidia-cufft-cu12>=11.2.3.61,<12.0 ; extra == 'and-cuda'
- - nvidia-curand-cu12>=10.3.6.82,<11.0 ; extra == 'and-cuda'
- - nvidia-cusolver-cu12>=11.6.3.83,<12.0 ; extra == 'and-cuda'
- - nvidia-cusparse-cu12>=12.5.1.3,<13.0 ; extra == 'and-cuda'
- - nvidia-nccl-cu12>=2.25.1,<3.0 ; extra == 'and-cuda'
- - nvidia-nvjitlink-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
- - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/ea/4c/c1aa90c5cc92e9f7f9c78421e121ef25bae7d378f8d1d4cbad46c6308836/tensorflow-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- name: tensorflow
- version: 2.20.0
- sha256: 47c88e05a07f1ead4977b4894b3ecd4d8075c40191065afc4fd9355c9db3d926
- requires_dist:
- - absl-py>=1.0.0
- - astunparse>=1.6.0
- - flatbuffers>=24.3.25
- - gast>=0.2.1,!=0.5.0,!=0.5.1,!=0.5.2
- - google-pasta>=0.1.1
- - libclang>=13.0.0
- - opt-einsum>=2.3.2
- - packaging
- - protobuf>=5.28.0
- - requests>=2.21.0,<3
- - setuptools
- - six>=1.12.0
- - termcolor>=1.1.0
- - typing-extensions>=3.6.6
- - wrapt>=1.11.0
- - grpcio>=1.24.3,<2.0
- - tensorboard~=2.20.0
- - keras>=3.10.0
- - numpy>=1.26.0
- - h5py>=3.11.0
- - ml-dtypes>=0.5.1,<1.0.0
- - nvidia-cublas-cu12>=12.5.3.2,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-cupti-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-nvcc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-nvrtc-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cuda-runtime-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - nvidia-cudnn-cu12>=9.3.0.75,<10.0 ; extra == 'and-cuda'
- - nvidia-cufft-cu12>=11.2.3.61,<12.0 ; extra == 'and-cuda'
- - nvidia-curand-cu12>=10.3.6.82,<11.0 ; extra == 'and-cuda'
- - nvidia-cusolver-cu12>=11.6.3.83,<12.0 ; extra == 'and-cuda'
- - nvidia-cusparse-cu12>=12.5.1.3,<13.0 ; extra == 'and-cuda'
- - nvidia-nccl-cu12>=2.25.1,<3.0 ; extra == 'and-cuda'
- - nvidia-nvjitlink-cu12>=12.5.82,<13.0 ; extra == 'and-cuda'
- - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.13' and sys_platform != 'win32' and extra == 'gcs-filesystem'
- - tensorflow-io-gcs-filesystem>=0.23.1 ; python_full_version < '3.12' and sys_platform == 'win32' and extra == 'gcs-filesystem'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl
- name: termcolor
- version: 3.3.0
- sha256: cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5
- requires_dist:
- - pytest ; extra == 'tests'
- - pytest-cov ; extra == 'tests'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/db/32/33ce509a79c207a39cf04bfa3ec3353da15d1e6553a6ad912f117cc29130/tf2onnx-1.8.4-py3-none-any.whl
- name: tf2onnx
- version: 1.8.4
- sha256: 1ebabb96c914da76e23222b6107a8b248a024bf259d77f027e6690099512d457
- requires_dist:
- - numpy>=1.14.1
- - onnx>=1.4.1
- - requests
- - six
- - flatbuffers
-- pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl
- name: threadpoolctl
- version: 3.6.0
- sha256: 43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb
- requires_python: '>=3.9'
-- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_ha0e22de_103.conda
- sha256: 1544760538a40bcd8ace2b1d8ebe3eb5807ac268641f8acdc18c69c5ebfeaf64
- md5: 86bc20552bf46075e3d92b67f089172d
+ size: 20772
+ timestamp: 1750436796633
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-0.4.1-hca56bd8_2.conda
+ sha256: d874906e236a5edc9309d479599bf2de4d8adca0f23c355b76759d5fb3c4bef8
+ md5: 159ffec8f7fab775669a538f0b29373a
+ depends:
+ - libgcc >=13
+ - libxcb >=1.17.0,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 21517
+ timestamp: 1750437961489
+- 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: []
+ size: 20829
+ timestamp: 1763366954390
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-cursor-0.1.6-he30d5cf_0.conda
+ sha256: 2e31eeeac0ad76229a565f1df3a8fb4ea54852a68404a99558adab9c92c0ac4d
+ md5: 8b70063c86f7f9a0b045e78d2d9971f7
+ depends:
+ - 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: []
+ size: 21639
+ timestamp: 1763367131001
+- 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: []
+ size: 24551
+ timestamp: 1718880534789
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-image-0.4.0-h5c728e9_2.conda
+ sha256: a43058edc001e8fb97f9b291028a6ca16a8969d9b56a998c7aecea083323ac97
+ md5: b82e5c78dbbfa931980e8bfe83bce913
+ depends:
+ - libgcc-ng >=12
+ - libxcb >=1.16,<2.0.0a0
+ - xcb-util >=0.4.1,<0.5.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 24910
+ timestamp: 1718880504308
+- 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: []
+ size: 14314
+ timestamp: 1718846569232
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-keysyms-0.4.1-h5c728e9_0.conda
+ sha256: 9d92daa7feb0e14f81bf0d4b3f0b6ff1e8cec3ff514df8a0c06c4d49b518c315
+ md5: 57ca8564599ddf8b633c4ea6afee6f3a
+ depends:
+ - libgcc-ng >=12
+ - libxcb >=1.16,<2.0.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 14343
+ timestamp: 1718846624153
+- 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: []
+ size: 16978
+ timestamp: 1718848865819
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-renderutil-0.3.10-h5c728e9_0.conda
+ sha256: 5827f5617c9741599f72bb7f090726f89c6ef91e4bada621895fdc2bbadfb0f1
+ md5: 7beeda4223c5484ef72d89fb66b7e8c1
+ depends:
+ - libgcc-ng >=12
+ - libxcb >=1.16,<2.0.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 18139
+ timestamp: 1718849914457
+- 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: []
+ size: 51689
+ timestamp: 1718844051451
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xcb-util-wm-0.4.2-h5c728e9_0.conda
+ sha256: 3f52cd8783e7d953c54266255fd11886c611c2620545eabc28ec8cf470ae8be7
+ md5: f14dcda6894722e421da2b7dcffb0b78
+ depends:
+ - libgcc-ng >=12
+ - libxcb >=1.16,<2.0.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 50772
+ timestamp: 1718845072660
+- conda: https://conda.anaconda.org/conda-forge/noarch/xgboost-3.1.2-cpu_pyhb39878e_2.conda
+ sha256: f19c4de7378c9bab3f84559876a37c76173ce9bd68131037d127b524d67fc128
+ md5: 54b0d6028470e445cc488f122aabbf0d
+ depends:
+ - py-xgboost 3.1.2 cpu_pyh718b53a_2
+ - python >=3.10
+ license: Apache-2.0
+ license_family: APACHE
+ purls: []
+ size: 16328
+ timestamp: 1765328652319
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.46-hb03c661_0.conda
+ sha256: aa03b49f402959751ccc6e21932d69db96a65a67343765672f7862332aa32834
+ md5: 71ae752a748962161b4740eaff510258
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - xorg-libx11 >=1.8.12,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 396975
+ timestamp: 1759543819846
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xkeyboard-config-2.46-he30d5cf_0.conda
+ sha256: c440a757d210e84c7f315ac3b034266980a8b4c986600649d296b9198b5b4f5e
+ md5: 9524f30d9dea7dd5d6ead43a8823b6c2
+ depends:
+ - libgcc >=14
+ - xorg-libx11 >=1.8.12,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 396706
+ timestamp: 1759543850920
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda
+ sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b
+ md5: fb901ff28063514abb6046c9ec2c4a45
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 58628
+ timestamp: 1734227592886
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda
+ sha256: a2ba1864403c7eb4194dacbfe2777acf3d596feae43aada8d1b478617ce45031
+ md5: c8d8ec3e00cd0fd8a231789b91a7c5b7
+ depends:
+ - libgcc >=13
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 60433
+ timestamp: 1734229908988
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda
+ sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250
+ md5: 1c74ff8c35dcadf952a16f752ca5aa49
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libuuid >=2.38.1,<3.0a0
+ - xorg-libice >=1.1.2,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 27590
+ timestamp: 1741896361728
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda
+ sha256: b86a819cd16f90c01d9d81892155126d01555a20dabd5f3091da59d6309afd0a
+ md5: 2d1409c50882819cb1af2de82e2b7208
+ depends:
+ - libgcc >=13
+ - libuuid >=2.38.1,<3.0a0
+ - xorg-libice >=1.1.2,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 28701
+ timestamp: 1741897678254
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.12-h4f16b4b_0.conda
+ sha256: 51909270b1a6c5474ed3978628b341b4d4472cd22610e5f22b506855a5e20f67
+ md5: db038ce880f100acc74dba10302b5630
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - libxcb >=1.17.0,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 835896
+ timestamp: 1741901112627
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.12-hca56bd8_0.conda
+ sha256: 452977d8ad96f04ec668ba74f46e70a53e00f99c0e0307956aeca75894c8131d
+ md5: 3df132f0048b9639bc091ef22937c111
+ depends:
+ - libgcc >=13
+ - libxcb >=1.17.0,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 864850
+ timestamp: 1741901264068
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda
+ sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b
+ md5: b2895afaf55bf96a8c8282a2e47a5de0
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 15321
+ timestamp: 1762976464266
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda
+ sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5
+ md5: 1c246e1105000c3660558459e2fd6d43
+ depends:
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 16317
+ timestamp: 1762977521691
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxau-1.0.12-hc919400_1.conda
+ sha256: adae11db0f66f86156569415ed79cda75b2dbf4bea48d1577831db701438164f
+ md5: 78b548eed8227a689f93775d5d23ae09
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 14105
+ timestamp: 1762976976084
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxcomposite-0.4.6-hb9d3cd8_2.conda
+ sha256: 753f73e990c33366a91fd42cc17a3d19bb9444b9ca5ff983605fa9e953baf57f
+ md5: d3c295b50f092ab525ffe3c2aa4b7413
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=13
- - libzlib >=1.3.1,<2.0a0
- constrains:
- - xorg-libx11 >=1.8.12,<2.0a0
- license: TCL
- license_family: BSD
+ - xorg-libx11 >=1.8.10,<2.0a0
+ - xorg-libxfixes >=6.0.1,<7.0a0
+ license: MIT
+ license_family: MIT
purls: []
- size: 3284905
- timestamp: 1763054914403
-- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h561c983_103.conda
- sha256: 154e73f6269f92ad5257aa2039278b083998fd19d371e150f307483fb93c07ae
- md5: 631db4799bc2bfe4daccf80bb3cbc433
+ size: 13603
+ timestamp: 1727884600744
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxcomposite-0.4.6-h86ecc28_2.conda
+ sha256: 0cb82160412adb6d83f03cf50e807a8e944682d556b2215992a6fbe9ced18bc0
+ md5: 86051eee0766c3542be24844a9c3cf36
depends:
- libgcc >=13
- - libzlib >=1.3.1,<2.0a0
- constrains:
- - xorg-libx11 >=1.8.12,<2.0a0
- license: TCL
- license_family: BSD
+ - xorg-libx11 >=1.8.9,<2.0a0
+ - xorg-libxfixes >=6.0.1,<7.0a0
+ license: MIT
+ license_family: MIT
purls: []
- size: 3333495
- timestamp: 1763059192223
-- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_3.conda
- sha256: ad0c67cb03c163a109820dc9ecf77faf6ec7150e942d1e8bb13e5d39dc058ab7
- md5: a73d54a5abba6543cb2f0af1bfbd6851
+ size: 13982
+ timestamp: 1727884626338
+- 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: []
+ size: 32533
+ timestamp: 1730908305254
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxcursor-1.2.3-h86ecc28_0.conda
+ sha256: c5d3692520762322a9598e7448492309f5ee9d8f3aff72d787cf06e77c42507f
+ md5: f2054759c2203d12d0007005e1f1296d
+ depends:
+ - libgcc >=13
+ - xorg-libx11 >=1.8.9,<2.0a0
+ - xorg-libxfixes >=6.0.1,<7.0a0
+ - xorg-libxrender >=0.9.11,<0.10.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 34596
+ timestamp: 1730908388714
+- 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: []
+ size: 13217
+ timestamp: 1727891438799
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdamage-1.1.6-h86ecc28_0.conda
+ sha256: 3afaa2f43eb4cb679fc0c3d9d7c50f0f2c80cc5d3df01d5d5fd60655d0bfa9be
+ md5: d5773c4e4d64428d7ddaa01f6f845dc7
+ depends:
+ - libgcc >=13
+ - xorg-libx11 >=1.8.9,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxfixes >=6.0.1,<7.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 13794
+ timestamp: 1727891406431
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda
+ sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142
+ md5: 1dafce8548e38671bea82e3f5c6ce22f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 20591
+ timestamp: 1762976546182
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda
+ sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1
+ md5: bff06dcde4a707339d66d45d96ceb2e2
+ depends:
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 21039
+ timestamp: 1762979038025
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xorg-libxdmcp-1.1.5-hc919400_1.conda
+ sha256: f7fa0de519d8da589995a1fe78ef74556bb8bc4172079ae3a8d20c3c81354906
+ md5: 9d1299ace1924aa8f4e0bc8e71dd0cf7
depends:
- __osx >=11.0
- - libzlib >=1.3.1,<2.0a0
- license: TCL
- license_family: BSD
+ license: MIT
+ license_family: MIT
purls: []
- size: 3125484
- timestamp: 1763055028377
-- conda: https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhcf101f3_3.conda
- sha256: fd30e43699cb22ab32ff3134d3acf12d6010b5bbaa63293c37076b50009b91f8
- md5: d0fc809fa4c4d85e959ce4ab6e1de800
+ size: 19156
+ timestamp: 1762977035194
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.6-hb9d3cd8_0.conda
+ sha256: da5dc921c017c05f38a38bd75245017463104457b63a1ce633ed41f214159c14
+ md5: febbab7d15033c913d53c7a2c102309d
depends:
- - python >=3.10
- - python
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - xorg-libx11 >=1.8.10,<2.0a0
license: MIT
license_family: MIT
- purls:
- - pkg:pypi/toml?source=hash-mapping
- size: 24017
- timestamp: 1764486833072
-- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.3.0-pyhcf101f3_0.conda
- sha256: cb77c660b646c00a48ef942a9e1721ee46e90230c7c570cdeb5a893b5cce9bff
- md5: d2732eb636c264dc9aa4cbee404b1a53
+ purls: []
+ size: 50060
+ timestamp: 1727752228921
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.6-h57736b2_0.conda
+ sha256: 8e216b024f52e367463b4173f237af97cf7053c77d9ce3e958bc62473a053f71
+ md5: bd1e86dd8aa3afd78a4bfdb4ef918165
depends:
- - python >=3.10
- - python
+ - libgcc >=13
+ - xorg-libx11 >=1.8.9,<2.0a0
license: MIT
license_family: MIT
- purls:
- - pkg:pypi/tomli?source=compressed-mapping
- size: 20973
- timestamp: 1760014679845
-- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.13.3-pyha770c72_0.conda
- sha256: f8d3b49c084831a20923f66826f30ecfc55a4cd951e544b7213c692887343222
- md5: 146402bf0f11cbeb8f781fa4309a95d3
+ purls: []
+ size: 50746
+ timestamp: 1727754268156
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda
+ sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4
+ md5: ba231da7fccf9ea1e768caf5c7099b84
depends:
- - python >=3.9
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - xorg-libx11 >=1.8.12,<2.0a0
license: MIT
license_family: MIT
- purls:
- - pkg:pypi/tomlkit?source=hash-mapping
- size: 38777
- timestamp: 1749127286558
-- pypi: https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl
- name: tqdm
- version: 4.67.1
- sha256: 26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2
- requires_dist:
- - colorama ; sys_platform == 'win32'
- - pytest>=6 ; extra == 'dev'
- - pytest-cov ; extra == 'dev'
- - pytest-timeout ; extra == 'dev'
- - pytest-asyncio>=0.24 ; extra == 'dev'
- - nbval ; extra == 'dev'
- - requests ; extra == 'discord'
- - slack-sdk ; extra == 'slack'
- - requests ; extra == 'telegram'
- - ipywidgets>=6 ; extra == 'notebook'
- requires_python: '>=3.7'
-- pypi: https://files.pythonhosted.org/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl
- name: typer
- version: 0.21.0
- sha256: c79c01ca6b30af9fd48284058a7056ba0d3bf5cf10d0ff3d0c5b11b68c258ac6
- requires_dist:
- - click>=8.0.0
- - typing-extensions>=3.7.4.3
- - shellingham>=1.3.0
- - rich>=10.11.0
- requires_python: '>=3.9'
-- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda
- sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731
- md5: 0caa1af407ecff61170c9437a808404d
+ purls: []
+ size: 20071
+ timestamp: 1759282564045
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda
+ sha256: 8cb9c88e25c57e47419e98f04f9ef3154ad96b9f858c88c570c7b91216a64d0e
+ md5: e8b4056544341daf1d415eaeae7a040c
depends:
- - python >=3.10
- - python
- license: PSF-2.0
- license_family: PSF
- purls:
- - pkg:pypi/typing-extensions?source=hash-mapping
- size: 51692
- timestamp: 1756220668932
-- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- name: tzdata
- version: '2025.3'
- sha256: 06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1
- requires_python: '>=2'
-- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-h8577fbf_0.conda
- sha256: 50fad5db6734d1bb73df1cf5db73215e326413d4b2137933f70708aa1840e25b
- md5: 338201218b54cadff2e774ac27733990
- license: LicenseRef-Public-Domain
+ - libgcc >=14
+ - xorg-libx11 >=1.8.12,<2.0a0
+ license: MIT
+ license_family: MIT
purls: []
- size: 119204
- timestamp: 1765745742795
-- pypi: https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl
- name: urllib3
- version: 2.6.2
- sha256: ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd
- requires_dist:
- - brotli>=1.2.0 ; platform_python_implementation == 'CPython' and extra == 'brotli'
- - brotlicffi>=1.2.0.0 ; platform_python_implementation != 'CPython' and extra == 'brotli'
- - h2>=4,<5 ; extra == 'h2'
- - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks'
- - backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl
- name: werkzeug
- version: 3.1.4
- sha256: 2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905
- requires_dist:
- - markupsafe>=2.1.1
- - watchdog>=2.3 ; extra == 'watchdog'
- requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl
- name: wheel
- version: 0.45.1
- sha256: 708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248
- requires_dist:
- - pytest>=6.0.0 ; extra == 'test'
- - setuptools>=65 ; extra == 'test'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
- name: wrapt
- version: 2.0.1
- sha256: c654eafb01afac55246053d67a4b9a984a3567c3808bb7df2f8de1c1caba2e1c
- requires_dist:
- - pytest ; extra == 'dev'
- - setuptools ; extra == 'dev'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- name: wrapt
- version: 2.0.1
- sha256: c8d60527d1ecfc131426b10d93ab5d53e08a09c5fa0175f6b21b3252080c70a9
- requires_dist:
- - pytest ; extra == 'dev'
- - setuptools ; extra == 'dev'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
- name: wrapt
- version: 2.0.1
- sha256: eb7cffe572ad0a141a7886a1d2efa5bef0bf7fe021deeea76b3ab334d2c38218
- requires_dist:
- - pytest ; extra == 'dev'
- - setuptools ; extra == 'dev'
- requires_python: '>=3.8'
-- pypi: https://files.pythonhosted.org/packages/5e/ab/c60fcc137fa685533bb31e721de3ecc88959d393830d59d0204c5cbd2c85/xgboost-3.1.2-py3-none-manylinux_2_28_x86_64.whl
- name: xgboost
- version: 3.1.2
- sha256: 24879ac75c0ee21acae0101f791bc43303f072a86d70fdfc89dae10a0008767f
- requires_dist:
- - numpy
- - nvidia-nccl-cu12 ; platform_machine != 'aarch64' and sys_platform == 'linux'
- - scipy
- - dask ; extra == 'dask'
- - distributed ; extra == 'dask'
- - pandas ; extra == 'dask'
- - pandas>=1.2 ; extra == 'pandas'
- - graphviz ; extra == 'plotting'
- - matplotlib ; extra == 'plotting'
- - cloudpickle ; extra == 'pyspark'
- - pyspark>=3.4 ; extra == 'pyspark'
- - scikit-learn ; extra == 'pyspark'
- - scikit-learn ; extra == 'scikit-learn'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/70/2f/5418f4b1deaf0886caf81c5e056299228ac2fc09b965a2dfe5e4496331c8/xgboost-3.1.2-py3-none-manylinux_2_28_aarch64.whl
- name: xgboost
- version: 3.1.2
- sha256: f9b83f39340e5852bbf3e918318e7feb7a2a700ac7e8603f9bc3a06787f0d86b
- requires_dist:
- - numpy
- - scipy
- - dask ; extra == 'dask'
- - distributed ; extra == 'dask'
- - pandas ; extra == 'dask'
- - pandas>=1.2 ; extra == 'pandas'
- - graphviz ; extra == 'plotting'
- - matplotlib ; extra == 'plotting'
- - cloudpickle ; extra == 'pyspark'
- - pyspark>=3.4 ; extra == 'pyspark'
- - scikit-learn ; extra == 'pyspark'
- - scikit-learn ; extra == 'scikit-learn'
- requires_python: '>=3.10'
-- pypi: https://files.pythonhosted.org/packages/f4/c6/ed928cb106f56ab73b3f4edb5287c1352251eb9225b5932d3dd5e2803f60/xgboost-3.1.2-py3-none-macosx_12_0_arm64.whl
- name: xgboost
- version: 3.1.2
- sha256: 09690f7430504fcd3b3e62bf826bb1282bb49873b68b07120d2696ab5638df41
- requires_dist:
- - numpy
- - nvidia-nccl-cu12 ; platform_machine != 'aarch64' and sys_platform == 'linux'
- - scipy
- - dask ; extra == 'dask'
- - distributed ; extra == 'dask'
- - pandas ; extra == 'dask'
- - pandas>=1.2 ; extra == 'pandas'
- - graphviz ; extra == 'plotting'
- - matplotlib ; extra == 'plotting'
- - cloudpickle ; extra == 'pyspark'
- - pyspark>=3.4 ; extra == 'pyspark'
- - scikit-learn ; extra == 'pyspark'
- - scikit-learn ; extra == 'scikit-learn'
- requires_python: '>=3.10'
+ size: 20704
+ timestamp: 1759284028146
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda
+ sha256: 1a724b47d98d7880f26da40e45f01728e7638e6ec69f35a3e11f92acd05f9e7a
+ md5: 17dcc85db3c7886650b8908b183d6876
+ 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: []
+ size: 47179
+ timestamp: 1727799254088
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda
+ sha256: 7b587407ecb9ccd2bbaf0fb94c5dbdde4d015346df063e9502dc0ce2b682fb5e
+ md5: eeee3bdb31c6acde2b81ad1b8c287087
+ depends:
+ - libgcc >=13
+ - xorg-libx11 >=1.8.9,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxfixes >=6.0.1,<7.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 48197
+ timestamp: 1727801059062
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.4-hb9d3cd8_0.conda
+ sha256: ac0f037e0791a620a69980914a77cb6bb40308e26db11698029d6708f5aa8e0d
+ md5: 2de7f99d6581a4a7adbff607b5c278ca
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - xorg-libx11 >=1.8.10,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxrender >=0.9.11,<0.10.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 29599
+ timestamp: 1727794874300
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.4-h86ecc28_0.conda
+ sha256: b2588a2b101d1b0a4e852532c8b9c92c59ef584fc762dd700567bdbf8cd00650
+ md5: dd3e74283a082381aa3860312e3c721e
+ depends:
+ - libgcc >=13
+ - xorg-libx11 >=1.8.9,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxrender >=0.9.11,<0.10.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 30197
+ timestamp: 1727794957221
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda
+ sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1
+ md5: 96d57aba173e878a2089d5638016dc5e
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - xorg-libx11 >=1.8.10,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 33005
+ timestamp: 1734229037766
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda
+ sha256: ffd77ee860c9635a28cfda46163dcfe9224dc6248c62404c544ae6b564a0be1f
+ md5: ae2c2dd0e2d38d249887727db2af960e
+ depends:
+ - libgcc >=13
+ - xorg-libx11 >=1.8.10,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 33649
+ timestamp: 1734229123157
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda
+ sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a
+ md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - xorg-libx11 >=1.8.10,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxi >=1.7.10,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 32808
+ timestamp: 1727964811275
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda
+ sha256: 6eaffce5a34fc0a16a21ddeaefb597e792a263b1b0c387c1ce46b0a967d558e1
+ md5: c05698071b5c8e0da82a282085845860
+ depends:
+ - libgcc >=13
+ - xorg-libx11 >=1.8.9,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ - xorg-libxi >=1.7.10,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 33786
+ timestamp: 1727964907993
+- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxxf86vm-1.1.6-hb9d3cd8_0.conda
+ sha256: 8a4e2ee642f884e6b78c20c0892b85dd9b2a6e64a6044e903297e616be6ca35b
+ md5: 5efa5fa6243a622445fdfd72aee15efa
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=13
+ - xorg-libx11 >=1.8.10,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 17819
+ timestamp: 1734214575628
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxxf86vm-1.1.6-h86ecc28_0.conda
+ sha256: 012f0d1fd9fb1d949e0dccc0b28d9dd5a8895a1f3e2a7edc1fa2e1b33fc0f233
+ md5: d745faa2d7c15092652e40a22bb261ed
+ depends:
+ - libgcc >=13
+ - xorg-libx11 >=1.8.10,<2.0a0
+ - xorg-libxext >=1.3.6,<2.0a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 18185
+ timestamp: 1734214652726
+- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda
+ sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad
+ md5: a77f85f77be52ff59391544bfe73390a
+ depends:
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 85189
+ timestamp: 1753484064210
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda
+ sha256: 66265e943f32ce02396ad214e27cb35f5b0490b3bd4f064446390f9d67fa5d88
+ md5: 032d8030e4a24fe1f72c74423a46fb88
+ depends:
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 88088
+ timestamp: 1753484092643
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda
+ sha256: b03433b13d89f5567e828ea9f1a7d5c5d697bf374c28a4168d71e9464f5dafac
+ md5: 78a0fe9e9c50d2c381e8ee47e3ea437d
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ purls: []
+ size: 83386
+ timestamp: 1753484079473
- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda
sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae
md5: 30cd29cb87d819caead4d55184c1d115
@@ -3789,6 +8306,40 @@ packages:
- pkg:pypi/zipp?source=compressed-mapping
size: 24194
timestamp: 1764460141901
+- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.2-hceb46e0_1.conda
+ sha256: f2b6a175677701a0b6ce556b3bd362dc94a4e36ffcd10e3860e52ca036b4ad96
+ md5: 40feea2979654ed579f1cda7c63ccb94
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 122303
+ timestamp: 1766076745735
+- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.2-ha7cb516_1.conda
+ sha256: 13b52eabab3e03b09f5c2e855ad7296890892b694c6efd88c514f85b032a2d1a
+ md5: 055d3357e5d6f57291a687c6983e1884
+ depends:
+ - libgcc >=14
+ - libstdcxx >=14
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 120684
+ timestamp: 1766077053538
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-ng-2.3.2-hed4e4f5_1.conda
+ sha256: ab481487381a6a6213d667e883252e52b8ca867b3b466c31a058126f964efffe
+ md5: 75f39a44c08cb5dc4ea847698de34ba3
+ depends:
+ - __osx >=11.0
+ - libcxx >=19
+ license: Zlib
+ license_family: Other
+ purls: []
+ size: 94882
+ timestamp: 1766076931977
- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7
md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829
@@ -3810,3 +8361,14 @@ packages:
purls: []
size: 614429
timestamp: 1764777145593
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda
+ sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9
+ md5: ab136e4c34e97f34fb621d2592a393d8
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ purls: []
+ size: 433413
+ timestamp: 1764777166076
diff --git a/pyproject.toml b/pyproject.toml
index 1c4402f..404a493 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,31 +6,31 @@ readme = "README.md"
authors = [
{ name = "Matthias De Smet", email = "matthias.desmet@ugent.be" },
]
-requires-python = ">=3.11,<3.14"
+requires-python = ">=3.12,<3.13"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
]
dependencies = [
- "pandas>=2.3.3,<3",
- "numpy>=2.4.0,<3",
- "scikit-learn>=1.8.0,<2",
- "tensorflow>=2.20.0,<3",
- "matplotlib>=3.10.8,<4",
- "statsmodels>=0.14.6,<0.15",
- "typer>=0.21.0,<0.22",
- "rich>=14.2.0,<15",
- "xgboost>=3.1.2,<4",
- "optuna>=4.6.0,<5",
- "optuna-integration[tfkeras]>=4.6.0,<5",
- "plotly>=6.5.0,<7",
- "kaleido>=1.2.0,<2",
- "onnx>=1.20.0,<2",
- "onnxmltools>=1.14.0,<2",
- "skl2onnx>=1.19.1,<2",
- "onnxconverter-common>=1.16.0,<2",
- "onnxruntime>=1.23.2,<2",
- "tf2onnx>=1.8.4,<2",
+ "kaleido",
+ "matplotlib",
+ "numpy",
+ "onnx",
+ "onnxconverter-common",
+ "onnxmltools",
+ "onnxruntime",
+ "optuna",
+ "optuna-integration[tfkeras]",
+ "pandas",
+ "plotly",
+ "rich",
+ "scikit-learn",
+ "skl2onnx",
+ "statsmodels",
+ "tensorflow",
+ "tf2onnx",
+ "typer",
+ "xgboost",
]
[build-system]
@@ -59,3 +59,20 @@ PREFACE = { path = ".", editable = true }
pylint = ">=4.0.4,<5"
pytest = ">=8,<9"
pytest-cov = ">=5,<6"
+python = "3.12.*"
+tf2onnx = ">=1.16.1,<2"
+tensorflow = ">=2.18.0,<3"
+onnxruntime = ">=1.22.2,<2"
+onnx = ">=1.17.0,<2"
+skl2onnx = ">=1.19.1,<2"
+matplotlib = ">=3.10.8,<4"
+numpy = ">=2.4.0,<3"
+onnxconverter-common = ">=1.16.0,<2"
+onnxmltools = ">=1.14.0,<2"
+optuna = ">=4.6.0,<5"
+pandas = ">=2.3.3,<3"
+plotly = ">=6.5.0,<7"
+rich = ">=14.2.0,<15"
+scikit-learn = ">=1.8.0,<2"
+typer = ">=0.21.0,<0.22"
+xgboost = ">=3.1.2,<4"
diff --git a/src/preface/lib/export_onnx.py b/src/preface/lib/export_onnx.py
index d1b8687..c78f96d 100644
--- a/src/preface/lib/export_onnx.py
+++ b/src/preface/lib/export_onnx.py
@@ -17,7 +17,7 @@
from preface.lib.xgboost import xgboost_export
-def _ensure_opset(model_proto: onnx.ModelProto, version: int = 13) -> onnx.ModelProto:
+def _ensure_opset(model_proto: onnx.ModelProto, version: int = 19) -> onnx.ModelProto:
"""
Force the default domain opset to a specific version.
"""
@@ -35,9 +35,9 @@ def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
pca_onnx = convert_sklearn(
pca,
initial_types=pca_initial_type,
- target_opset=13,
+ target_opset=18,
)
- _ensure_opset(pca_onnx, 13) # type: ignore
+ _ensure_opset(pca_onnx, 19) # type: ignore
return pca_onnx # type: ignore
@@ -70,9 +70,9 @@ def ensemble_export(
# 1. Convert Imputer
initial_type = [("input", FloatTensorType([None, input_dim]))]
imputer_onnx = convert_sklearn(
- imputer, initial_types=initial_type, target_opset={"": 13, "ai.onnx.ml": 2}
+ imputer, initial_types=initial_type, target_opset=18
)
- _ensure_opset(imputer_onnx, 13) # type: ignore
+ _ensure_opset(imputer_onnx, 19) # type: ignore
# Prefix Imputer
imputer_onnx = add_prefix(imputer_onnx, prefix="imputer_") # type: ignore
diff --git a/src/preface/lib/functions.py b/src/preface/lib/functions.py
index 21bced5..c42631d 100644
--- a/src/preface/lib/functions.py
+++ b/src/preface/lib/functions.py
@@ -60,5 +60,5 @@ def fit_rlm(x_values: npt.NDArray, y_values: npt.NDArray) -> tuple[float, float]
def pca_export(pca: PCA, input_dim: int) -> onnx.ModelProto:
"""Export PCA model to ONNX format."""
initial_type = [("input", FloatTensorType([None, input_dim]))]
- pca_onnx = convert_sklearn(pca, initial_types=initial_type, target_opset=13)
+ pca_onnx = convert_sklearn(pca, initial_types=initial_type, target_opset=18)
return pca_onnx # type: ignore
diff --git a/src/preface/lib/impute.py b/src/preface/lib/impute.py
index e5b4eaf..e567588 100644
--- a/src/preface/lib/impute.py
+++ b/src/preface/lib/impute.py
@@ -87,5 +87,5 @@ def impute_export(
initial_type = [("impute_input", FloatTensorType([None, input_dim]))]
- imputer_onnx = convert_sklearn(imputer, initial_types=initial_type, target_opset=13)
+ imputer_onnx = convert_sklearn(imputer, initial_types=initial_type, target_opset=18)
return imputer_onnx # type: ignore
diff --git a/src/preface/lib/neural.py b/src/preface/lib/neural.py
index 7747c87..a1d492f 100644
--- a/src/preface/lib/neural.py
+++ b/src/preface/lib/neural.py
@@ -160,6 +160,6 @@ def neural_export(model: Model) -> onnx.ModelProto:
"""Export neural network to ONNX format."""
initial_type = [("neural_input", FloatTensorType([None, model.input_shape[1]]))]
onnx_model = onnxmltools.convert_keras(
- model, initial_types=initial_type, target_opset=13
+ model, initial_types=initial_type, target_opset=18
)
return onnx_model
diff --git a/src/preface/lib/svm.py b/src/preface/lib/svm.py
index 00a865a..c75cbc0 100644
--- a/src/preface/lib/svm.py
+++ b/src/preface/lib/svm.py
@@ -89,6 +89,6 @@ def svm_export(model: SVR) -> onnx.ModelProto:
"""Export SVM model to ONNX format."""
initial_type = [("svm_input", FloatTensorType([None, model.n_features_in_]))]
onnx_model = onnxmltools.convert_sklearn(
- model, initial_types=initial_type, target_opset=13
+ model, initial_types=initial_type, target_opset=18
)
return onnx_model # type: ignore
diff --git a/src/preface/lib/xgboost.py b/src/preface/lib/xgboost.py
index 3217f49..d290a6f 100644
--- a/src/preface/lib/xgboost.py
+++ b/src/preface/lib/xgboost.py
@@ -7,9 +7,11 @@
from sklearn.model_selection import GroupShuffleSplit
from xgboost import XGBRegressor
from sklearn.decomposition import PCA
-import onnxmltools
-from onnxmltools.convert.common.data_types import FloatTensorType
-
+from skl2onnx.common.data_types import FloatTensorType
+from skl2onnx import to_onnx, update_registered_converter
+from skl2onnx.common.shape_calculator import calculate_linear_regressor_output_shapes
+from skl2onnx.convert import may_switch_bases_classes_order
+from onnxmltools.convert.xgboost.operator_converters.XGBoost import convert_xgboost
from preface.lib.impute import impute_nan, ImputeOptions
@@ -104,8 +106,15 @@ def xgboost_fit(
def xgboost_export(model: XGBRegressor) -> onnx.ModelProto:
"""Export XGBoost model to ONNX format."""
- initial_type = [("xgboost_input", FloatTensorType([None, model.n_features_in_]))]
- onnx_model = onnxmltools.convert_xgboost(
- model, initial_types=initial_type, target_opset=13
+ update_registered_converter(
+ XGBRegressor,
+ "XGBoostXGBRegressor",
+ calculate_linear_regressor_output_shapes,
+ convert_xgboost,
)
+
+ with may_switch_bases_classes_order(XGBRegressor):
+ initial_type = [("xgboost_input", FloatTensorType([None, model.n_features_in_]))]
+ onnx_model = to_onnx(model, initial_types=initial_type, target_opset=18)
+
return onnx_model