Compare commits
6 Commits
ef0ce7db89
...
ef311d862e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef311d862e | ||
|
|
cd4dc583e8 | ||
|
|
a936b754cb | ||
|
|
37ac637c9c | ||
|
|
8a5adc6360 | ||
|
|
44da3c2bd9 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -23,8 +23,5 @@
|
||||
*.nav
|
||||
*.snm
|
||||
*.mp4
|
||||
*.png
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.npy
|
||||
|
||||
|
||||
103
Deep-SAD-PyTorch/devenv.lock
Normal file
103
Deep-SAD-PyTorch/devenv.lock
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"nodes": {
|
||||
"devenv": {
|
||||
"locked": {
|
||||
"dir": "src/modules",
|
||||
"lastModified": 1754730435,
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "d1388a093a7225c2abe8c244109c5a4490de4077",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"dir": "src/modules",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1747046372,
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1754416808,
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "9c52372878df6911f9afc1e2a1391f55e4dfc864",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1754299112,
|
||||
"owner": "cachix",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"rev": "16c21c9f5c6fb978466e91182a248dd8ca1112ac",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "rolling",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"git-hooks": "git-hooks",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": [
|
||||
"git-hooks"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
24
Deep-SAD-PyTorch/devenv.nix
Normal file
24
Deep-SAD-PyTorch/devenv.nix
Normal file
@@ -0,0 +1,24 @@
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
native_dependencies = with pkgs.python312Packages; [
|
||||
torch-bin
|
||||
torchvision-bin
|
||||
aggdraw # for visualtorch
|
||||
];
|
||||
tools = with pkgs; [
|
||||
ruff
|
||||
];
|
||||
in
|
||||
{
|
||||
packages = native_dependencies ++ tools;
|
||||
languages.python = {
|
||||
enable = true;
|
||||
package = pkgs.python312;
|
||||
uv = {
|
||||
enable = true;
|
||||
sync.enable = true;
|
||||
};
|
||||
venv.enable = true;
|
||||
};
|
||||
|
||||
}
|
||||
17
Deep-SAD-PyTorch/devenv.yaml
Normal file
17
Deep-SAD-PyTorch/devenv.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
||||
inputs:
|
||||
nixpkgs:
|
||||
url: github:cachix/devenv-nixpkgs/rolling
|
||||
|
||||
allowUnfree: true
|
||||
cudaSupport: true
|
||||
# If you're using non-OSS software, you can set allowUnfree to true.
|
||||
# allowUnfree: true
|
||||
|
||||
# If you're willing to use a package that's vulnerable
|
||||
# permittedInsecurePackages:
|
||||
# - "openssl-1.1.1w"
|
||||
|
||||
# If you have more than one devenv you can merge them
|
||||
#imports:
|
||||
# - ./backend
|
||||
@@ -12,6 +12,8 @@ dependencies = [
|
||||
"kiwisolver>=1.4.8",
|
||||
"matplotlib>=3.10.3",
|
||||
"numpy>=2.3.1",
|
||||
"onnx>=1.18.0",
|
||||
"onnxscript>=0.3.2",
|
||||
"pandas>=2.3.0",
|
||||
"pillow>=11.2.1",
|
||||
"pyparsing>=3.2.3",
|
||||
@@ -23,6 +25,7 @@ dependencies = [
|
||||
"six>=1.17.0",
|
||||
"torch-receptive-field",
|
||||
"torchscan>=0.1.1",
|
||||
"visualtorch>=0.2.4",
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from pathlib import Path
|
||||
|
||||
import torch
|
||||
import torch.onnx
|
||||
from networks.mnist_LeNet import MNIST_LeNet_Autoencoder
|
||||
|
||||
from networks.subter_LeNet import SubTer_LeNet_Autoencoder
|
||||
from networks.subter_LeNet_rf import SubTer_Efficient_AE
|
||||
|
||||
|
||||
def export_model_to_onnx(model, filepath, input_shape=(1, 1, 28, 28)):
|
||||
def export_model_to_onnx(model, filepath):
|
||||
model.eval() # Set the model to evaluation mode
|
||||
dummy_input = torch.randn(input_shape) # Create a dummy input tensor
|
||||
dummy_input = torch.randn(model.input_dim) # Create a dummy input tensor
|
||||
torch.onnx.export(
|
||||
model, # model being run
|
||||
dummy_input, # model input (or a tuple for multiple inputs)
|
||||
@@ -23,13 +27,17 @@ def export_model_to_onnx(model, filepath, input_shape=(1, 1, 28, 28)):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Initialize the autoencoder model
|
||||
autoencoder = MNIST_LeNet_Autoencoder(rep_dim=32)
|
||||
output_folder_path = Path("./onnx_models")
|
||||
output_folder_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Define the file path where the ONNX model will be saved
|
||||
onnx_file_path = "mnist_lenet_autoencoder.onnx"
|
||||
models_to_visualize = [
|
||||
(
|
||||
SubTer_LeNet_Autoencoder(rep_dim=32),
|
||||
output_folder_path / "subter_lenet_ae.onnx",
|
||||
),
|
||||
(SubTer_Efficient_AE(rep_dim=32), output_folder_path / "subter_ef_ae.onnx"),
|
||||
]
|
||||
|
||||
# Export the model
|
||||
export_model_to_onnx(autoencoder, onnx_file_path)
|
||||
|
||||
print(f"Model has been exported to {onnx_file_path}")
|
||||
for model, output_path in models_to_visualize:
|
||||
export_model_to_onnx(model, output_path)
|
||||
print(f"Model has been exported to {output_path}")
|
||||
|
||||
998
Deep-SAD-PyTorch/uv.lock
generated
Normal file
998
Deep-SAD-PyTorch/uv.lock
generated
Normal file
@@ -0,0 +1,998 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
requires-python = ">=3.12"
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.13'",
|
||||
"python_full_version < '3.13'",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aggdraw"
|
||||
version = "1.3.19"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/03/f1/031b1205f1f580c41566a509166f7097cbff13adffd0c1080b0b3e0ea4ae/aggdraw-1.3.19.tar.gz", hash = "sha256:e78a23b29fb66a079832bae5604f082bfa4ff9d5d469c77506a67253d7fee7db", size = 260414, upload-time = "2024-09-11T16:59:53.445Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/93/aeab2f4832c10975eacf051296d6f674951e597a92ff64d7d397159b9ef5/aggdraw-1.3.19-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:e68afe82d0bbd111b2d6d7f41ac8cf13a010cd65ad095117c2e9fd8252710a73", size = 479651, upload-time = "2024-09-11T16:59:31.408Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/99/2e7bbcca4be5e00656555041245f293cda360c2524d5ddf40f3a9bbfdf7b/aggdraw-1.3.19-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f3ff2595490b3760658a28afdca5111ed787bd1fccdab5c81d0ea57e0fe5a8c", size = 975835, upload-time = "2024-09-11T16:59:33.54Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/81/b845347ef6d399dafa7ac3e8dfe5993d71d2c73d52a1c21a429bb7e459ea/aggdraw-1.3.19-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56bbcc8d4f64e60ed815419837b9d2ba579169d92c4fe19e4caa3679aaedb6aa", size = 1000009, upload-time = "2024-09-11T16:59:35.31Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/64/0b8fef4d67d928043f9a24a7f65223d3734ea10c24ff0ca3bacbd888b4c1/aggdraw-1.3.19-cp312-cp312-win_amd64.whl", hash = "sha256:6a39bdf2f1043ca4148a926e35feaa1d4d592c25c8b225d8d0ad945415bab7cc", size = 45060, upload-time = "2024-09-11T16:59:37.055Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/9c/05ed3a30b8b6f40da118cf4ffa52599d33ecb49e0f4b10d3f0c9e4d6fbea/aggdraw-1.3.19-cp312-cp312-win_arm64.whl", hash = "sha256:21f951129b3014b3cf678b250ba5e4345d93243602b4062804e6111319d0eaf3", size = 34196, upload-time = "2024-09-11T16:59:38.045Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/75/eb67b18d131cf08b68db7bd2cb971e58280a3a6c216f662f92751e11bd77/aggdraw-1.3.19-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f7cb8141620ec4cb3be55601115126d9a1b084ef5bdea0bb510007efa42e8cfe", size = 479637, upload-time = "2024-09-11T16:59:39.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/ed/dd15ed34166139f0fc1ae8956b6aa4657b38e209e6bd35f1ee4617690c15/aggdraw-1.3.19-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aecacc4f6d13b8343ac07624576bab4dadd4528f0c47f54b2fae0656fc913670", size = 975787, upload-time = "2024-09-11T16:59:41.145Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/46/c5b9094701787d11e40c7bfced2c081fb59e9afc740722bb0d71f5e0335d/aggdraw-1.3.19-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:981210dbcbb649d80763a8ae32b845ff517103718c6bb0a95bae5b9d5d1c8cd2", size = 999932, upload-time = "2024-09-11T16:59:42.576Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/11/a0d24b499e4f5800817e4760ad0be3c51713a458b1030df0e5192fae5d57/aggdraw-1.3.19-cp313-cp313-win_amd64.whl", hash = "sha256:41e09faf469cae11339f5d1b0680dba7ec02502efebc10086f1a142a8a39afb8", size = 45067, upload-time = "2024-09-11T16:59:43.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/1f/fe05b249ee116ba5c659b6e312ddc2a22dc1490f8869c2478404be220b23/aggdraw-1.3.19-cp313-cp313-win_arm64.whl", hash = "sha256:e5552ac136225692a774d481a9baa0736c68739f64b7a7ec9f4cc5f69c8a789a", size = 34185, upload-time = "2024-09-11T16:59:44.859Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "contourpy"
|
||||
version = "1.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/34/f7/44785876384eff370c251d58fd65f6ad7f39adce4a093c934d4a67a7c6b6/contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2", size = 271580, upload-time = "2025-04-15T17:37:03.105Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/3b/0004767622a9826ea3d95f0e9d98cd8729015768075d61f9fea8eeca42a8/contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15", size = 255530, upload-time = "2025-04-15T17:37:07.026Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/bb/7bd49e1f4fa805772d9fd130e0d375554ebc771ed7172f48dfcd4ca61549/contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92", size = 307688, upload-time = "2025-04-15T17:37:11.481Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/97/e1d5dbbfa170725ef78357a9a0edc996b09ae4af170927ba8ce977e60a5f/contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87", size = 347331, upload-time = "2025-04-15T17:37:18.212Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/66/e69e6e904f5ecf6901be3dd16e7e54d41b6ec6ae3405a535286d4418ffb4/contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415", size = 318963, upload-time = "2025-04-15T17:37:22.76Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/32/b8a1c8965e4f72482ff2d1ac2cd670ce0b542f203c8e1d34e7c3e6925da7/contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe", size = 323681, upload-time = "2025-04-15T17:37:33.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/c6/12a7e6811d08757c7162a541ca4c5c6a34c0f4e98ef2b338791093518e40/contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441", size = 1308674, upload-time = "2025-04-15T17:37:48.64Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/8a/bebe5a3f68b484d3a2b8ffaf84704b3e343ef1addea528132ef148e22b3b/contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e", size = 1380480, upload-time = "2025-04-15T17:38:06.7Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/db/fcd325f19b5978fb509a7d55e06d99f5f856294c1991097534360b307cf1/contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912", size = 178489, upload-time = "2025-04-15T17:38:10.338Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/c8/fadd0b92ffa7b5eb5949bf340a63a4a496a6930a6c37a7ba0f12acb076d6/contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73", size = 223042, upload-time = "2025-04-15T17:38:14.239Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630, upload-time = "2025-04-15T17:38:19.142Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670, upload-time = "2025-04-15T17:38:23.688Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694, upload-time = "2025-04-15T17:38:28.238Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986, upload-time = "2025-04-15T17:38:33.502Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060, upload-time = "2025-04-15T17:38:38.672Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747, upload-time = "2025-04-15T17:38:43.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895, upload-time = "2025-04-15T17:39:00.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098, upload-time = "2025-04-15T17:43:29.649Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535, upload-time = "2025-04-15T17:44:44.532Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096, upload-time = "2025-04-15T17:44:48.194Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090, upload-time = "2025-04-15T17:43:34.084Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643, upload-time = "2025-04-15T17:43:38.626Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443, upload-time = "2025-04-15T17:43:44.522Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865, upload-time = "2025-04-15T17:43:49.545Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162, upload-time = "2025-04-15T17:43:54.203Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355, upload-time = "2025-04-15T17:44:01.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935, upload-time = "2025-04-15T17:44:17.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168, upload-time = "2025-04-15T17:44:33.43Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550, upload-time = "2025-04-15T17:44:37.092Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214, upload-time = "2025-04-15T17:44:40.827Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cvxopt"
|
||||
version = "1.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/12/8467d16008ab7577259d32f1e59c4d84edda22b7729ab4a1a0dfd5f0550b/cvxopt-1.3.2.tar.gz", hash = "sha256:3461fa42c1b2240ba4da1d985ca73503914157fc4c77417327ed6d7d85acdbe6", size = 4108454, upload-time = "2023-08-09T14:31:17.514Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/10/dc/1c21715e1267ca29f562e4450426d1ff8a7ffcc3e670100cec332a105b95/cvxopt-1.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25adbeb0efd50d7ea4f07e5f5bd390a3c807df907f03efb86b018807c2c8cfbe", size = 13836586, upload-time = "2023-12-22T12:05:40.049Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/c8/a04048143d0329ccd36403951746c1a6b5f1fc56c479e5a0a77efb2064b2/cvxopt-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c10e27cb7a27b55f17e0df30c6b85e98c9672a7bdb7000a7509560eee7679137", size = 12765513, upload-time = "2023-12-22T12:05:43.608Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/17/ee82c745c5bda340a4dd812652c42fb71efd45f663554a10c3ec45f230df/cvxopt-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8bcf71a5016aeb24e597dc099564e8de809e0bc5d6af21e26422586aea26718", size = 17870231, upload-time = "2023-12-22T14:05:33.01Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/f9/467c3f4682f3dbfbd7ff67f2307ed746a86b6dcc6b0b62cf1eeaebbd9d74/cvxopt-1.3.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a581e6c87a06371210184f64353055ff7c917d49363901ae0c527da139095082", size = 13846494, upload-time = "2024-10-21T20:50:42.583Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/8e/c3869928250e12ad9264da388bc70150a9de039e233b815a6a3bd2b8b8ae/cvxopt-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be7800ac4556d8920aaf8e4e2d89348aafd5d585642aabf9eeecb09a2659fbca", size = 9529949, upload-time = "2024-10-21T20:50:45.165Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/ad/edce467c24529c536fc9de787546a1c8eca293009383a872b6f638d22eae/cvxopt-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:a92ebfc5df77fea57544f8ad2102bfc45af0e77ac4dfe98ed1b9628e8bba77c3", size = 12845277, upload-time = "2023-12-22T12:05:47.516Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/c5/3e70e50c4c478acd3fefe3ea51b7e42ad661ce5a265a72b3dba175ce10fc/cvxopt-1.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:2f9135eea23c9b781574e0cadc5738cf5651a8fd8de822b6de1260411523bfd1", size = 16873224, upload-time = "2024-10-21T20:48:37.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/96/e42b9ec38e1bbe9bf85a5fc9cc7feb173de5a874889735072b49a7d4d8d0/cvxopt-1.3.2-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d7921768712db156e6ec92ac21f7ce52069feb1fb994868d0ca795498111fbac", size = 12424739, upload-time = "2024-10-21T20:48:40.325Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/08/2c621ad782e9ff7f921c2244c6b4bcbc72ca756cb33021295c288123c465/cvxopt-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af63db45ba559e3e15180fbec140d8a4ff612d8f21d989181a4e8479fa3b8b6", size = 17869707, upload-time = "2024-10-21T20:48:42.881Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/60/583a1ef8e2e259bdd1bf32fccd4ea15aef4aad5854746ec59cbb2462eb92/cvxopt-1.3.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:8fe178ac780a8bccf425a08004d853eae43b3ddcf7617521fb35c63550077b17", size = 13846614, upload-time = "2024-10-21T20:48:46.26Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/2b/d8721b046a3c8bff494490a01ef1eeacf1f970f0d1274448856ccbe0475c/cvxopt-1.3.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:a47a95d7848e6fe768b55910bac8bb114c5f1f355f5a6590196d5e9bdf775d2f", size = 21277032, upload-time = "2024-10-21T20:48:49.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/19/b1e1c16895a36cc504bf7a940e88431b82b18ca10cbce81072860b9e3d60/cvxopt-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e863238d64a4b4443b8be53a08f6b94eda6ec1727038c330da02014f7c19e1be", size = 9530674, upload-time = "2024-10-21T20:48:51.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/cc/ac0705749f96cc52f8d30c9c06e54dc8d4c04ef9c2d21aeed1ae2ee63dab/cvxopt-1.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c56965415afd8a493cc4af3587960751f8780057ca3de8c6be97217156e4633", size = 13725340, upload-time = "2024-10-21T20:48:55.074Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/f2/7e3c3f51e8e6b325bf00bfc37036f1f58bd9a5c29bbd88fb2eef2ebc0ac2/cvxopt-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:85c3b52c1353b294c597b169cc901f5274d8bb8776908ccad66fec7a14b69519", size = 16226402, upload-time = "2024-10-21T20:48:57.616Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/55/90b40b489a235a9f35a532eb77cec81782e466779d9a531ffda6b2f99410/cvxopt-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:0a0987966009ad383de0918e61255d34ed9ebc783565bcb15470d4155010b6bf", size = 12845323, upload-time = "2024-10-21T20:49:00.581Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cycler"
|
||||
version = "0.12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deep-sad-pytorch"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "cvxopt" },
|
||||
{ name = "cycler" },
|
||||
{ name = "joblib" },
|
||||
{ name = "kiwisolver" },
|
||||
{ name = "matplotlib" },
|
||||
{ name = "numpy" },
|
||||
{ name = "onnx" },
|
||||
{ name = "onnxscript" },
|
||||
{ name = "pandas" },
|
||||
{ name = "pillow" },
|
||||
{ name = "pyparsing" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "pytz" },
|
||||
{ name = "scikit-learn" },
|
||||
{ name = "scipy" },
|
||||
{ name = "seaborn" },
|
||||
{ name = "six" },
|
||||
{ name = "torch-receptive-field" },
|
||||
{ name = "torchscan" },
|
||||
{ name = "visualtorch" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "click", specifier = ">=8.2.1" },
|
||||
{ name = "cvxopt", specifier = ">=1.3.2" },
|
||||
{ name = "cycler", specifier = ">=0.12.1" },
|
||||
{ name = "joblib", specifier = ">=1.5.1" },
|
||||
{ name = "kiwisolver", specifier = ">=1.4.8" },
|
||||
{ name = "matplotlib", specifier = ">=3.10.3" },
|
||||
{ name = "numpy", specifier = ">=2.3.1" },
|
||||
{ name = "onnx", specifier = ">=1.18.0" },
|
||||
{ name = "onnxscript", specifier = ">=0.3.2" },
|
||||
{ name = "pandas", specifier = ">=2.3.0" },
|
||||
{ name = "pillow", specifier = ">=11.2.1" },
|
||||
{ name = "pyparsing", specifier = ">=3.2.3" },
|
||||
{ name = "python-dateutil", specifier = ">=2.9.0.post0" },
|
||||
{ name = "pytz", specifier = ">=2025.2" },
|
||||
{ name = "scikit-learn", specifier = ">=1.7.0" },
|
||||
{ name = "scipy", specifier = ">=1.16.0" },
|
||||
{ name = "seaborn", specifier = ">=0.13.2" },
|
||||
{ name = "six", specifier = ">=1.17.0" },
|
||||
{ name = "torch-receptive-field", git = "https://github.com/Fangyh09/pytorch-receptive-field.git" },
|
||||
{ name = "torchscan", specifier = ">=0.1.1" },
|
||||
{ name = "visualtorch", specifier = ">=0.2.4" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.18.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fonttools"
|
||||
version = "4.58.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2e/5a/1124b2c8cb3a8015faf552e92714040bcdbc145dfa29928891b02d147a18/fonttools-4.58.4.tar.gz", hash = "sha256:928a8009b9884ed3aae17724b960987575155ca23c6f0b8146e400cc9e0d44ba", size = 3525026, upload-time = "2025-06-13T17:25:15.426Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/3c/1d1792bfe91ef46f22a3d23b4deb514c325e73c17d4f196b385b5e2faf1c/fonttools-4.58.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:462211c0f37a278494e74267a994f6be9a2023d0557aaa9ecbcbfce0f403b5a6", size = 2754082, upload-time = "2025-06-13T17:24:24.862Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/1f/2b261689c901a1c3bc57a6690b0b9fc21a9a93a8b0c83aae911d3149f34e/fonttools-4.58.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0c7a12fb6f769165547f00fcaa8d0df9517603ae7e04b625e5acb8639809b82d", size = 2321677, upload-time = "2025-06-13T17:24:26.815Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/6b/4607add1755a1e6581ae1fc0c9a640648e0d9cdd6591cc2d581c2e07b8c3/fonttools-4.58.4-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2d42c63020a922154add0a326388a60a55504629edc3274bc273cd3806b4659f", size = 4896354, upload-time = "2025-06-13T17:24:28.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/95/34b4f483643d0cb11a1f830b72c03fdd18dbd3792d77a2eb2e130a96fada/fonttools-4.58.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f2b4e6fd45edc6805f5f2c355590b092ffc7e10a945bd6a569fc66c1d2ae7aa", size = 4941633, upload-time = "2025-06-13T17:24:30.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/ac/9bafbdb7694059c960de523e643fa5a61dd2f698f3f72c0ca18ae99257c7/fonttools-4.58.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f155b927f6efb1213a79334e4cb9904d1e18973376ffc17a0d7cd43d31981f1e", size = 4886170, upload-time = "2025-06-13T17:24:32.724Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/44/a3a3b70d5709405f7525bb7cb497b4e46151e0c02e3c8a0e40e5e9fe030b/fonttools-4.58.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e38f687d5de97c7fb7da3e58169fb5ba349e464e141f83c3c2e2beb91d317816", size = 5037851, upload-time = "2025-06-13T17:24:35.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/cb/e8923d197c78969454eb876a4a55a07b59c9c4c46598f02b02411dc3b45c/fonttools-4.58.4-cp312-cp312-win32.whl", hash = "sha256:636c073b4da9db053aa683db99580cac0f7c213a953b678f69acbca3443c12cc", size = 2187428, upload-time = "2025-06-13T17:24:36.996Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/e6/fe50183b1a0e1018e7487ee740fa8bb127b9f5075a41e20d017201e8ab14/fonttools-4.58.4-cp312-cp312-win_amd64.whl", hash = "sha256:82e8470535743409b30913ba2822e20077acf9ea70acec40b10fcf5671dceb58", size = 2236649, upload-time = "2025-06-13T17:24:38.985Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/4f/c05cab5fc1a4293e6bc535c6cb272607155a0517700f5418a4165b7f9ec8/fonttools-4.58.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5f4a64846495c543796fa59b90b7a7a9dff6839bd852741ab35a71994d685c6d", size = 2745197, upload-time = "2025-06-13T17:24:40.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/d3/49211b1f96ae49308f4f78ca7664742377a6867f00f704cdb31b57e4b432/fonttools-4.58.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e80661793a5d4d7ad132a2aa1eae2e160fbdbb50831a0edf37c7c63b2ed36574", size = 2317272, upload-time = "2025-06-13T17:24:43.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/11/c9972e46a6abd752a40a46960e431c795ad1f306775fc1f9e8c3081a1274/fonttools-4.58.4-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fe5807fc64e4ba5130f1974c045a6e8d795f3b7fb6debfa511d1773290dbb76b", size = 4877184, upload-time = "2025-06-13T17:24:45.527Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/24/5017c01c9ef8df572cc9eaf9f12be83ad8ed722ff6dc67991d3d752956e4/fonttools-4.58.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b610b9bef841cb8f4b50472494158b1e347d15cad56eac414c722eda695a6cfd", size = 4939445, upload-time = "2025-06-13T17:24:47.647Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/b0/538cc4d0284b5a8826b4abed93a69db52e358525d4b55c47c8cef3669767/fonttools-4.58.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2daa7f0e213c38f05f054eb5e1730bd0424aebddbeac094489ea1585807dd187", size = 4878800, upload-time = "2025-06-13T17:24:49.766Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/9b/a891446b7a8250e65bffceb248508587958a94db467ffd33972723ab86c9/fonttools-4.58.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:66cccb6c0b944496b7f26450e9a66e997739c513ffaac728d24930df2fd9d35b", size = 5021259, upload-time = "2025-06-13T17:24:51.754Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/b2/c4d2872cff3ace3ddd1388bf15b76a1d8d5313f0a61f234e9aed287e674d/fonttools-4.58.4-cp313-cp313-win32.whl", hash = "sha256:94d2aebb5ca59a5107825520fde596e344652c1f18170ef01dacbe48fa60c889", size = 2185824, upload-time = "2025-06-13T17:24:54.324Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/57/cddf8bcc911d4f47dfca1956c1e3aeeb9f7c9b8e88b2a312fe8c22714e0b/fonttools-4.58.4-cp313-cp313-win_amd64.whl", hash = "sha256:b554bd6e80bba582fd326ddab296e563c20c64dca816d5e30489760e0c41529f", size = 2236382, upload-time = "2025-06-13T17:24:56.291Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/2f/c536b5b9bb3c071e91d536a4d11f969e911dbb6b227939f4c5b0bca090df/fonttools-4.58.4-py3-none-any.whl", hash = "sha256:a10ce13a13f26cbb9f37512a4346bb437ad7e002ff6fa966a7ce7ff5ac3528bd", size = 1114660, upload-time = "2025-06-13T17:25:13.321Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fsspec"
|
||||
version = "2025.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/00/f7/27f15d41f0ed38e8fcc488584b57e902b331da7f7c6dcda53721b15838fc/fsspec-2025.5.1.tar.gz", hash = "sha256:2e55e47a540b91843b755e83ded97c6e897fa0942b11490113f09e9c443c2475", size = 303033, upload-time = "2025-05-24T12:03:23.792Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/61/78c7b3851add1481b048b5fdc29067397a1784e2910592bc81bb3f608635/fsspec-2025.5.1-py3-none-any.whl", hash = "sha256:24d3a2e663d5fc735ab256263c4075f374a174c3410c0b25e5bd1970bceaa462", size = 199052, upload-time = "2025-05-24T12:03:21.66Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "joblib"
|
||||
version = "1.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dc/fe/0f5a938c54105553436dbff7a61dc4fed4b1b2c98852f8833beaf4d5968f/joblib-1.5.1.tar.gz", hash = "sha256:f4f86e351f39fe3d0d32a9f2c3d8af1ee4cec285aafcb27003dda5205576b444", size = 330475, upload-time = "2025-05-23T12:04:37.097Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/4f/1195bbac8e0c2acc5f740661631d8d750dc38d4a32b23ee5df3cde6f4e0d/joblib-1.5.1-py3-none-any.whl", hash = "sha256:4719a31f054c7d766948dcd83e9613686b27114f190f717cec7eaa2084f8a74a", size = 307746, upload-time = "2025-05-23T12:04:35.124Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kiwisolver"
|
||||
version = "1.4.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/82/59/7c91426a8ac292e1cdd53a63b6d9439abd573c875c3f92c146767dd33faf/kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e", size = 97538, upload-time = "2024-12-24T18:30:51.519Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/aa/cea685c4ab647f349c3bc92d2daf7ae34c8e8cf405a6dcd3a497f58a2ac3/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d6af5e8815fd02997cb6ad9bbed0ee1e60014438ee1a5c2444c96f87b8843502", size = 124152, upload-time = "2024-12-24T18:29:16.85Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/0b/8db6d2e2452d60d5ebc4ce4b204feeb16176a851fd42462f66ade6808084/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bade438f86e21d91e0cf5dd7c0ed00cda0f77c8c1616bd83f9fc157fa6760d31", size = 66555, upload-time = "2024-12-24T18:29:19.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/26/d6a0db6785dd35d3ba5bf2b2df0aedc5af089962c6eb2cbf67a15b81369e/kiwisolver-1.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b83dc6769ddbc57613280118fb4ce3cd08899cc3369f7d0e0fab518a7cf37fdb", size = 65067, upload-time = "2024-12-24T18:29:20.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/ed/1d97f7e3561e09757a196231edccc1bcf59d55ddccefa2afc9c615abd8e0/kiwisolver-1.4.8-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111793b232842991be367ed828076b03d96202c19221b5ebab421ce8bcad016f", size = 1378443, upload-time = "2024-12-24T18:29:22.843Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/61/39d30b99954e6b46f760e6289c12fede2ab96a254c443639052d1b573fbc/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:257af1622860e51b1a9d0ce387bf5c2c4f36a90594cb9514f55b074bcc787cfc", size = 1472728, upload-time = "2024-12-24T18:29:24.463Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/3e/804163b932f7603ef256e4a715e5843a9600802bb23a68b4e08c8c0ff61d/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b5637c3f316cab1ec1c9a12b8c5f4750a4c4b71af9157645bf32830e39c03a", size = 1478388, upload-time = "2024-12-24T18:29:25.776Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/9e/60eaa75169a154700be74f875a4d9961b11ba048bef315fbe89cb6999056/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:782bb86f245ec18009890e7cb8d13a5ef54dcf2ebe18ed65f795e635a96a1c6a", size = 1413849, upload-time = "2024-12-24T18:29:27.202Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/b3/9458adb9472e61a998c8c4d95cfdfec91c73c53a375b30b1428310f923e4/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc978a80a0db3a66d25767b03688f1147a69e6237175c0f4ffffaaedf744055a", size = 1475533, upload-time = "2024-12-24T18:29:28.638Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/7a/0a42d9571e35798de80aef4bb43a9b672aa7f8e58643d7bd1950398ffb0a/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:36dbbfd34838500a31f52c9786990d00150860e46cd5041386f217101350f0d3", size = 2268898, upload-time = "2024-12-24T18:29:30.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/07/1255dc8d80271400126ed8db35a1795b1a2c098ac3a72645075d06fe5c5d/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eaa973f1e05131de5ff3569bbba7f5fd07ea0595d3870ed4a526d486fe57fa1b", size = 2425605, upload-time = "2024-12-24T18:29:33.151Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/df/5a3b4cf13780ef6f6942df67b138b03b7e79e9f1f08f57c49957d5867f6e/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a66f60f8d0c87ab7f59b6fb80e642ebb29fec354a4dfad687ca4092ae69d04f4", size = 2375801, upload-time = "2024-12-24T18:29:34.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/10/2348d068e8b0f635c8c86892788dac7a6b5c0cb12356620ab575775aad89/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858416b7fb777a53f0c59ca08190ce24e9abbd3cffa18886a5781b8e3e26f65d", size = 2520077, upload-time = "2024-12-24T18:29:36.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/d8/014b89fee5d4dce157d814303b0fce4d31385a2af4c41fed194b173b81ac/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:085940635c62697391baafaaeabdf3dd7a6c3643577dde337f4d66eba021b2b8", size = 2338410, upload-time = "2024-12-24T18:29:39.991Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/72/dfff0cc97f2a0776e1c9eb5bef1ddfd45f46246c6533b0191887a427bca5/kiwisolver-1.4.8-cp312-cp312-win_amd64.whl", hash = "sha256:01c3d31902c7db5fb6182832713d3b4122ad9317c2c5877d0539227d96bb2e50", size = 71853, upload-time = "2024-12-24T18:29:42.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/85/220d13d914485c0948a00f0b9eb419efaf6da81b7d72e88ce2391f7aed8d/kiwisolver-1.4.8-cp312-cp312-win_arm64.whl", hash = "sha256:a3c44cb68861de93f0c4a8175fbaa691f0aa22550c331fefef02b618a9dcb476", size = 65424, upload-time = "2024-12-24T18:29:44.38Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/b3/e62464a652f4f8cd9006e13d07abad844a47df1e6537f73ddfbf1bc997ec/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1c8ceb754339793c24aee1c9fb2485b5b1f5bb1c2c214ff13368431e51fc9a09", size = 124156, upload-time = "2024-12-24T18:29:45.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/2d/f13d06998b546a2ad4f48607a146e045bbe48030774de29f90bdc573df15/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a62808ac74b5e55a04a408cda6156f986cefbcf0ada13572696b507cc92fa1", size = 66555, upload-time = "2024-12-24T18:29:46.37Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/e3/b8bd14b0a54998a9fd1e8da591c60998dc003618cb19a3f94cb233ec1511/kiwisolver-1.4.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68269e60ee4929893aad82666821aaacbd455284124817af45c11e50a4b42e3c", size = 65071, upload-time = "2024-12-24T18:29:47.333Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/1c/6c86f6d85ffe4d0ce04228d976f00674f1df5dc893bf2dd4f1928748f187/kiwisolver-1.4.8-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34d142fba9c464bc3bbfeff15c96eab0e7310343d6aefb62a79d51421fcc5f1b", size = 1378053, upload-time = "2024-12-24T18:29:49.636Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/b9/1c6e9f6dcb103ac5cf87cb695845f5fa71379021500153566d8a8a9fc291/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc373e0eef45b59197de815b1b28ef89ae3955e7722cc9710fb91cd77b7f47", size = 1472278, upload-time = "2024-12-24T18:29:51.164Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/81/aca1eb176de671f8bda479b11acdc42c132b61a2ac861c883907dde6debb/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77e6f57a20b9bd4e1e2cedda4d0b986ebd0216236f0106e55c28aea3d3d69b16", size = 1478139, upload-time = "2024-12-24T18:29:52.594Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/f4/e081522473671c97b2687d380e9e4c26f748a86363ce5af48b4a28e48d06/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08e77738ed7538f036cd1170cbed942ef749137b1311fa2bbe2a7fda2f6bf3cc", size = 1413517, upload-time = "2024-12-24T18:29:53.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/e9/6a7d025d8da8c4931522922cd706105aa32b3291d1add8c5427cdcd66e63/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5ce1e481a74b44dd5e92ff03ea0cb371ae7a0268318e202be06c8f04f4f1246", size = 1474952, upload-time = "2024-12-24T18:29:56.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/13/13fa685ae167bee5d94b415991c4fc7bb0a1b6ebea6e753a87044b209678/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fc2ace710ba7c1dfd1a3b42530b62b9ceed115f19a1656adefce7b1782a37794", size = 2269132, upload-time = "2024-12-24T18:29:57.989Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/92/bb7c9395489b99a6cb41d502d3686bac692586db2045adc19e45ee64ed23/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3452046c37c7692bd52b0e752b87954ef86ee2224e624ef7ce6cb21e8c41cc1b", size = 2425997, upload-time = "2024-12-24T18:29:59.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/12/87f0e9271e2b63d35d0d8524954145837dd1a6c15b62a2d8c1ebe0f182b4/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7e9a60b50fe8b2ec6f448fe8d81b07e40141bfced7f896309df271a0b92f80f3", size = 2376060, upload-time = "2024-12-24T18:30:01.338Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/6e/c8af39288edbce8bf0fa35dee427b082758a4b71e9c91ef18fa667782138/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:918139571133f366e8362fa4a297aeba86c7816b7ecf0bc79168080e2bd79957", size = 2520471, upload-time = "2024-12-24T18:30:04.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/78/df381bc7b26e535c91469f77f16adcd073beb3e2dd25042efd064af82323/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e063ef9f89885a1d68dd8b2e18f5ead48653176d10a0e324e3b0030e3a69adeb", size = 2338793, upload-time = "2024-12-24T18:30:06.25Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/dc/c1abe38c37c071d0fc71c9a474fd0b9ede05d42f5a458d584619cfd2371a/kiwisolver-1.4.8-cp313-cp313-win_amd64.whl", hash = "sha256:a17b7c4f5b2c51bb68ed379defd608a03954a1845dfed7cc0117f1cc8a9b7fd2", size = 71855, upload-time = "2024-12-24T18:30:07.535Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/b6/21529d595b126ac298fdd90b705d87d4c5693de60023e0efcb4f387ed99e/kiwisolver-1.4.8-cp313-cp313-win_arm64.whl", hash = "sha256:3cd3bc628b25f74aedc6d374d5babf0166a92ff1317f46267f12d2ed54bc1d30", size = 65430, upload-time = "2024-12-24T18:30:08.504Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/bd/b89380b7298e3af9b39f49334e3e2a4af0e04819789f04b43d560516c0c8/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:370fd2df41660ed4e26b8c9d6bbcad668fbe2560462cba151a721d49e5b6628c", size = 126294, upload-time = "2024-12-24T18:30:09.508Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/41/5857dc72e5e4148eaac5aa76e0703e594e4465f8ab7ec0fc60e3a9bb8fea/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:84a2f830d42707de1d191b9490ac186bf7997a9495d4e9072210a1296345f7dc", size = 67736, upload-time = "2024-12-24T18:30:11.039Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/d1/be059b8db56ac270489fb0b3297fd1e53d195ba76e9bbb30e5401fa6b759/kiwisolver-1.4.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7a3ad337add5148cf51ce0b55642dc551c0b9d6248458a757f98796ca7348712", size = 66194, upload-time = "2024-12-24T18:30:14.886Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/83/4b73975f149819eb7dcf9299ed467eba068ecb16439a98990dcb12e63fdd/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7506488470f41169b86d8c9aeff587293f530a23a23a49d6bc64dab66bedc71e", size = 1465942, upload-time = "2024-12-24T18:30:18.927Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/2c/30a5cdde5102958e602c07466bce058b9d7cb48734aa7a4327261ac8e002/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f0121b07b356a22fb0414cec4666bbe36fd6d0d759db3d37228f496ed67c880", size = 1595341, upload-time = "2024-12-24T18:30:22.102Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/9b/1e71db1c000385aa069704f5990574b8244cce854ecd83119c19e83c9586/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6d6bd87df62c27d4185de7c511c6248040afae67028a8a22012b010bc7ad062", size = 1598455, upload-time = "2024-12-24T18:30:24.947Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/92/c8fec52ddf06231b31cbb779af77e99b8253cd96bd135250b9498144c78b/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:291331973c64bb9cce50bbe871fb2e675c4331dab4f31abe89f175ad7679a4d7", size = 1522138, upload-time = "2024-12-24T18:30:26.286Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/51/9eb7e2cd07a15d8bdd976f6190c0164f92ce1904e5c0c79198c4972926b7/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:893f5525bb92d3d735878ec00f781b2de998333659507d29ea4466208df37bed", size = 1582857, upload-time = "2024-12-24T18:30:28.86Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/95/c5a00387a5405e68ba32cc64af65ce881a39b98d73cc394b24143bebc5b8/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b47a465040146981dc9db8647981b8cb96366fbc8d452b031e4f8fdffec3f26d", size = 2293129, upload-time = "2024-12-24T18:30:30.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/83/eeb7af7d706b8347548313fa3a3a15931f404533cc54fe01f39e830dd231/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:99cea8b9dd34ff80c521aef46a1dddb0dcc0283cf18bde6d756f1e6f31772165", size = 2421538, upload-time = "2024-12-24T18:30:33.334Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/f9/27e94c1b3eb29e6933b6986ffc5fa1177d2cd1f0c8efc5f02c91c9ac61de/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:151dffc4865e5fe6dafce5480fab84f950d14566c480c08a53c663a0020504b6", size = 2390661, upload-time = "2024-12-24T18:30:34.939Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/d4/3c9735faa36ac591a4afcc2980d2691000506050b7a7e80bcfe44048daa7/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:577facaa411c10421314598b50413aa1ebcf5126f704f1e5d72d7e4e9f020d90", size = 2546710, upload-time = "2024-12-24T18:30:37.281Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/fa/be89a49c640930180657482a74970cdcf6f7072c8d2471e1babe17a222dc/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:be4816dc51c8a471749d664161b434912eee82f2ea66bd7628bd14583a833e85", size = 2349213, upload-time = "2024-12-24T18:30:40.019Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matplotlib"
|
||||
version = "3.10.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "contourpy" },
|
||||
{ name = "cycler" },
|
||||
{ name = "fonttools" },
|
||||
{ name = "kiwisolver" },
|
||||
{ name = "numpy" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pillow" },
|
||||
{ name = "pyparsing" },
|
||||
{ name = "python-dateutil" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/26/91/d49359a21893183ed2a5b6c76bec40e0b1dcbf8ca148f864d134897cfc75/matplotlib-3.10.3.tar.gz", hash = "sha256:2f82d2c5bb7ae93aaaa4cd42aca65d76ce6376f83304fa3a630b569aca274df0", size = 34799811, upload-time = "2025-05-08T19:10:54.39Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/43/6b80eb47d1071f234ef0c96ca370c2ca621f91c12045f1401b5c9b28a639/matplotlib-3.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0ab1affc11d1f495ab9e6362b8174a25afc19c081ba5b0775ef00533a4236eea", size = 8179689, upload-time = "2025-05-08T19:10:07.602Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/70/d61a591958325c357204870b5e7b164f93f2a8cca1dc6ce940f563909a13/matplotlib-3.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a818d8bdcafa7ed2eed74487fdb071c09c1ae24152d403952adad11fa3c65b4", size = 8050466, upload-time = "2025-05-08T19:10:09.383Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/75/70c9d2306203148cc7902a961240c5927dd8728afedf35e6a77e105a2985/matplotlib-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748ebc3470c253e770b17d8b0557f0aa85cf8c63fd52f1a61af5b27ec0b7ffee", size = 8456252, upload-time = "2025-05-08T19:10:11.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/91/ba0ae1ff4b3f30972ad01cd4a8029e70a0ec3b8ea5be04764b128b66f763/matplotlib-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed70453fd99733293ace1aec568255bc51c6361cb0da94fa5ebf0649fdb2150a", size = 8601321, upload-time = "2025-05-08T19:10:14.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/88/d636041eb54a84b889e11872d91f7cbf036b3b0e194a70fa064eb8b04f7a/matplotlib-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dbed9917b44070e55640bd13419de83b4c918e52d97561544814ba463811cbc7", size = 9406972, upload-time = "2025-05-08T19:10:16.569Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/79/0d1c165eac44405a86478082e225fce87874f7198300bbebc55faaf6d28d/matplotlib-3.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:cf37d8c6ef1a48829443e8ba5227b44236d7fcaf7647caa3178a4ff9f7a5be05", size = 8067954, upload-time = "2025-05-08T19:10:18.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/c1/23cfb566a74c696a3b338d8955c549900d18fe2b898b6e94d682ca21e7c2/matplotlib-3.10.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9f2efccc8dcf2b86fc4ee849eea5dcaecedd0773b30f47980dc0cbeabf26ec84", size = 8180318, upload-time = "2025-05-08T19:10:20.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/0c/02f1c3b66b30da9ee343c343acbb6251bef5b01d34fad732446eaadcd108/matplotlib-3.10.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3ddbba06a6c126e3301c3d272a99dcbe7f6c24c14024e80307ff03791a5f294e", size = 8051132, upload-time = "2025-05-08T19:10:22.569Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/ab/8db1a5ac9b3a7352fb914133001dae889f9fcecb3146541be46bed41339c/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748302b33ae9326995b238f606e9ed840bf5886ebafcb233775d946aa8107a15", size = 8457633, upload-time = "2025-05-08T19:10:24.749Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/64/41c4367bcaecbc03ef0d2a3ecee58a7065d0a36ae1aa817fe573a2da66d4/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a80fcccbef63302c0efd78042ea3c2436104c5b1a4d3ae20f864593696364ac7", size = 8601031, upload-time = "2025-05-08T19:10:27.03Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/6f/6cc79e9e5ab89d13ed64da28898e40fe5b105a9ab9c98f83abd24e46d7d7/matplotlib-3.10.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55e46cbfe1f8586adb34f7587c3e4f7dedc59d5226719faf6cb54fc24f2fd52d", size = 9406988, upload-time = "2025-05-08T19:10:29.056Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/0f/eed564407bd4d935ffabf561ed31099ed609e19287409a27b6d336848653/matplotlib-3.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:151d89cb8d33cb23345cd12490c76fd5d18a56581a16d950b48c6ff19bb2ab93", size = 8068034, upload-time = "2025-05-08T19:10:31.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/e5/2f14791ff69b12b09e9975e1d116d9578ac684460860ce542c2588cb7a1c/matplotlib-3.10.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c26dd9834e74d164d06433dc7be5d75a1e9890b926b3e57e74fa446e1a62c3e2", size = 8218223, upload-time = "2025-05-08T19:10:33.114Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/08/30a94afd828b6e02d0a52cae4a29d6e9ccfcf4c8b56cc28b021d3588873e/matplotlib-3.10.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:24853dad5b8c84c8c2390fc31ce4858b6df504156893292ce8092d190ef8151d", size = 8094985, upload-time = "2025-05-08T19:10:35.337Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/44/f3bc6b53066c889d7a1a3ea8094c13af6a667c5ca6220ec60ecceec2dabe/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f7878214d369d7d4215e2a9075fef743be38fa401d32e6020bab2dfabaa566", size = 8483109, upload-time = "2025-05-08T19:10:37.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/c7/473bc559beec08ebee9f86ca77a844b65747e1a6c2691e8c92e40b9f42a8/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6929fc618cb6db9cb75086f73b3219bbb25920cb24cee2ea7a12b04971a4158", size = 8618082, upload-time = "2025-05-08T19:10:39.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/e9/6ce8edd264c8819e37bbed8172e0ccdc7107fe86999b76ab5752276357a4/matplotlib-3.10.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c7818292a5cc372a2dc4c795e5c356942eb8350b98ef913f7fda51fe175ac5d", size = 9413699, upload-time = "2025-05-08T19:10:42.376Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/92/9a45c91089c3cf690b5badd4be81e392ff086ccca8a1d4e3a08463d8a966/matplotlib-3.10.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4f23ffe95c5667ef8a2b56eea9b53db7f43910fa4a2d5472ae0f72b64deab4d5", size = 8139044, upload-time = "2025-05-08T19:10:44.551Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ml-dtypes"
|
||||
version = "0.5.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/78/a7/aad060393123cfb383956dca68402aff3db1e1caffd5764887ed5153f41b/ml_dtypes-0.5.3.tar.gz", hash = "sha256:95ce33057ba4d05df50b1f3cfefab22e351868a843b3b15a46c65836283670c9", size = 692316, upload-time = "2025-07-29T18:39:19.454Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/eb/bc07c88a6ab002b4635e44585d80fa0b350603f11a2097c9d1bfacc03357/ml_dtypes-0.5.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:156418abeeda48ea4797db6776db3c5bdab9ac7be197c1233771e0880c304057", size = 663864, upload-time = "2025-07-29T18:38:33.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/89/11af9b0f21b99e6386b6581ab40fb38d03225f9de5f55cf52097047e2826/ml_dtypes-0.5.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1db60c154989af253f6c4a34e8a540c2c9dce4d770784d426945e09908fbb177", size = 4951313, upload-time = "2025-07-29T18:38:36.45Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/a9/b98b86426c24900b0c754aad006dce2863df7ce0bb2bcc2c02f9cc7e8489/ml_dtypes-0.5.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1b255acada256d1fa8c35ed07b5f6d18bc21d1556f842fbc2d5718aea2cd9e55", size = 4928805, upload-time = "2025-07-29T18:38:38.29Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/c1/85e6be4fc09c6175f36fb05a45917837f30af9a5146a5151cb3a3f0f9e09/ml_dtypes-0.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:da65e5fd3eea434ccb8984c3624bc234ddcc0d9f4c81864af611aaebcc08a50e", size = 208182, upload-time = "2025-07-29T18:38:39.72Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/17/cf5326d6867be057f232d0610de1458f70a8ce7b6290e4b4a277ea62b4cd/ml_dtypes-0.5.3-cp312-cp312-win_arm64.whl", hash = "sha256:8bb9cd1ce63096567f5f42851f5843b5a0ea11511e50039a7649619abfb4ba6d", size = 161560, upload-time = "2025-07-29T18:38:41.072Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/87/1bcc98a66de7b2455dfb292f271452cac9edc4e870796e0d87033524d790/ml_dtypes-0.5.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5103856a225465371fe119f2fef737402b705b810bd95ad5f348e6e1a6ae21af", size = 663781, upload-time = "2025-07-29T18:38:42.984Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/2c/bd2a79ba7c759ee192b5601b675b180a3fd6ccf48ffa27fe1782d280f1a7/ml_dtypes-0.5.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cae435a68861660af81fa3c5af16b70ca11a17275c5b662d9c6f58294e0f113", size = 4956217, upload-time = "2025-07-29T18:38:44.65Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/f3/091ba84e5395d7fe5b30c081a44dec881cd84b408db1763ee50768b2ab63/ml_dtypes-0.5.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6936283b56d74fbec431ca57ce58a90a908fdbd14d4e2d22eea6d72bb208a7b7", size = 4933109, upload-time = "2025-07-29T18:38:46.405Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/24/054036dbe32c43295382c90a1363241684c4d6aaa1ecc3df26bd0c8d5053/ml_dtypes-0.5.3-cp313-cp313-win_amd64.whl", hash = "sha256:d0f730a17cf4f343b2c7ad50cee3bd19e969e793d2be6ed911f43086460096e4", size = 208187, upload-time = "2025-07-29T18:38:48.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/3d/7dc3ec6794a4a9004c765e0c341e32355840b698f73fd2daff46f128afc1/ml_dtypes-0.5.3-cp313-cp313-win_arm64.whl", hash = "sha256:2db74788fc01914a3c7f7da0763427280adfc9cd377e9604b6b64eb8097284bd", size = 161559, upload-time = "2025-07-29T18:38:50.493Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/91/e6c7a0d67a152b9330445f9f0cf8ae6eee9b83f990b8c57fe74631e42a90/ml_dtypes-0.5.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:93c36a08a6d158db44f2eb9ce3258e53f24a9a4a695325a689494f0fdbc71770", size = 689321, upload-time = "2025-07-29T18:38:52.03Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/6c/b7b94b84a104a5be1883305b87d4c6bd6ae781504474b4cca067cb2340ec/ml_dtypes-0.5.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0e44a3761f64bc009d71ddb6d6c71008ba21b53ab6ee588dadab65e2fa79eafc", size = 5274495, upload-time = "2025-07-29T18:38:53.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/38/6266604dffb43378055394ea110570cf261a49876fc48f548dfe876f34cc/ml_dtypes-0.5.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bdf40d2aaabd3913dec11840f0d0ebb1b93134f99af6a0a4fd88ffe924928ab4", size = 5285422, upload-time = "2025-07-29T18:38:56.603Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/88/8612ff177d043a474b9408f0382605d881eeb4125ba89d4d4b3286573a83/ml_dtypes-0.5.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:aec640bd94c4c85c0d11e2733bd13cbb10438fb004852996ec0efbc6cacdaf70", size = 661182, upload-time = "2025-07-29T18:38:58.414Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/2b/0569a5e88b29240d373e835107c94ae9256fb2191d3156b43b2601859eff/ml_dtypes-0.5.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bda32ce212baa724e03c68771e5c69f39e584ea426bfe1a701cb01508ffc7035", size = 4956187, upload-time = "2025-07-29T18:39:00.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/66/273c2a06ae44562b104b61e6b14444da00061fd87652506579d7eb2c40b1/ml_dtypes-0.5.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c205cac07d24a29840c163d6469f61069ce4b065518519216297fc2f261f8db9", size = 4930911, upload-time = "2025-07-29T18:39:02.405Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/ab/606be3e87dc0821bd360c8c1ee46108025c31a4f96942b63907bb441b87d/ml_dtypes-0.5.3-cp314-cp314-win_amd64.whl", hash = "sha256:cd7c0bb22d4ff86d65ad61b5dd246812e8993fbc95b558553624c33e8b6903ea", size = 216664, upload-time = "2025-07-29T18:39:03.927Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/a2/e900690ca47d01dffffd66375c5de8c4f8ced0f1ef809ccd3b25b3e6b8fa/ml_dtypes-0.5.3-cp314-cp314-win_arm64.whl", hash = "sha256:9d55ea7f7baf2aed61bf1872116cefc9d0c3693b45cae3916897ee27ef4b835e", size = 160203, upload-time = "2025-07-29T18:39:05.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/21/783dfb51f40d2660afeb9bccf3612b99f6a803d980d2a09132b0f9d216ab/ml_dtypes-0.5.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:e12e29764a0e66a7a31e9b8bf1de5cc0423ea72979f45909acd4292de834ccd3", size = 689324, upload-time = "2025-07-29T18:39:07.567Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/f7/a82d249c711abf411ac027b7163f285487f5e615c3e0716c61033ce996ab/ml_dtypes-0.5.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19f6c3a4f635c2fc9e2aa7d91416bd7a3d649b48350c51f7f715a09370a90d93", size = 5275917, upload-time = "2025-07-29T18:39:09.339Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/3c/541c4b30815ab90ebfbb51df15d0b4254f2f9f1e2b4907ab229300d5e6f2/ml_dtypes-0.5.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ab039ffb40f3dc0aeeeba84fd6c3452781b5e15bef72e2d10bcb33e4bbffc39", size = 5285284, upload-time = "2025-07-29T18:39:11.532Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mpmath"
|
||||
version = "1.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "networkx"
|
||||
version = "3.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/4f/ccdb8ad3a38e583f214547fd2f7ff1fc160c43a75af88e6aec213404b96a/networkx-3.5.tar.gz", hash = "sha256:d4c6f9cf81f52d69230866796b82afbccdec3db7ae4fbd1b65ea750feed50037", size = 2471065, upload-time = "2025-05-29T11:35:07.804Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec", size = 2034406, upload-time = "2025-05-29T11:35:04.961Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2e/19/d7c972dfe90a353dbd3efbbe1d14a5951de80c99c9dc1b93cd998d51dc0f/numpy-2.3.1.tar.gz", hash = "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b", size = 20390372, upload-time = "2025-06-21T12:28:33.469Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/56/71ad5022e2f63cfe0ca93559403d0edef14aea70a841d640bd13cdba578e/numpy-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d", size = 20896664, upload-time = "2025-06-21T12:15:30.845Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/65/2db52ba049813670f7f987cc5db6dac9be7cd95e923cc6832b3d32d87cef/numpy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29", size = 14131078, upload-time = "2025-06-21T12:15:52.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/dd/28fa3c17b0e751047ac928c1e1b6990238faad76e9b147e585b573d9d1bd/numpy-2.3.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc", size = 5112554, upload-time = "2025-06-21T12:16:01.434Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/fc/84ea0cba8e760c4644b708b6819d91784c290288c27aca916115e3311d17/numpy-2.3.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943", size = 6646560, upload-time = "2025-06-21T12:16:11.895Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/b2/512b0c2ddec985ad1e496b0bd853eeb572315c0f07cd6997473ced8f15e2/numpy-2.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25", size = 14260638, upload-time = "2025-06-21T12:16:32.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/45/c51cb248e679a6c6ab14b7a8e3ead3f4a3fe7425fc7a6f98b3f147bec532/numpy-2.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660", size = 16632729, upload-time = "2025-06-21T12:16:57.439Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/ff/feb4be2e5c09a3da161b412019caf47183099cbea1132fd98061808c2df2/numpy-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952", size = 15565330, upload-time = "2025-06-21T12:17:20.638Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/6d/ceafe87587101e9ab0d370e4f6e5f3f3a85b9a697f2318738e5e7e176ce3/numpy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77", size = 18361734, upload-time = "2025-06-21T12:17:47.938Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/19/0fb49a3ea088be691f040c9bf1817e4669a339d6e98579f91859b902c636/numpy-2.3.1-cp312-cp312-win32.whl", hash = "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab", size = 6320411, upload-time = "2025-06-21T12:17:58.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/3e/e28f4c1dd9e042eb57a3eb652f200225e311b608632bc727ae378623d4f8/numpy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76", size = 12734973, upload-time = "2025-06-21T12:18:17.601Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/a8/8a5e9079dc722acf53522b8f8842e79541ea81835e9b5483388701421073/numpy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30", size = 10191491, upload-time = "2025-06-21T12:18:33.585Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/bd/35ad97006d8abff8631293f8ea6adf07b0108ce6fec68da3c3fcca1197f2/numpy-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8", size = 20889381, upload-time = "2025-06-21T12:19:04.103Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/4f/df5923874d8095b6062495b39729178eef4a922119cee32a12ee1bd4664c/numpy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e", size = 14152726, upload-time = "2025-06-21T12:19:25.599Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0", size = 5105145, upload-time = "2025-06-21T12:19:34.782Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/63/a7f7fd5f375b0361682f6ffbf686787e82b7bbd561268e4f30afad2bb3c0/numpy-2.3.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d", size = 6639409, upload-time = "2025-06-21T12:19:45.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/0d/1854a4121af895aab383f4aa233748f1df4671ef331d898e32426756a8a6/numpy-2.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1", size = 14257630, upload-time = "2025-06-21T12:20:06.544Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/30/af1b277b443f2fb08acf1c55ce9d68ee540043f158630d62cef012750f9f/numpy-2.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1", size = 16627546, upload-time = "2025-06-21T12:20:31.002Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/ec/3b68220c277e463095342d254c61be8144c31208db18d3fd8ef02712bcd6/numpy-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0", size = 15562538, upload-time = "2025-06-21T12:20:54.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/2b/4014f2bcc4404484021c74d4c5ee8eb3de7e3f7ac75f06672f8dcf85140a/numpy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8", size = 18360327, upload-time = "2025-06-21T12:21:21.053Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/8d/2ddd6c9b30fcf920837b8672f6c65590c7d92e43084c25fc65edc22e93ca/numpy-2.3.1-cp313-cp313-win32.whl", hash = "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8", size = 6312330, upload-time = "2025-06-21T12:25:07.447Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/c8/beaba449925988d415efccb45bf977ff8327a02f655090627318f6398c7b/numpy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42", size = 12731565, upload-time = "2025-06-21T12:25:26.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/c3/5c0c575d7ec78c1126998071f58facfc124006635da75b090805e642c62e/numpy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e", size = 10190262, upload-time = "2025-06-21T12:25:42.196Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/19/a029cd335cf72f79d2644dcfc22d90f09caa86265cbbde3b5702ccef6890/numpy-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8", size = 20987593, upload-time = "2025-06-21T12:21:51.664Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/91/8ea8894406209107d9ce19b66314194675d31761fe2cb3c84fe2eeae2f37/numpy-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb", size = 14300523, upload-time = "2025-06-21T12:22:13.583Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/7f/06187b0066eefc9e7ce77d5f2ddb4e314a55220ad62dd0bfc9f2c44bac14/numpy-2.3.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee", size = 5227993, upload-time = "2025-06-21T12:22:22.53Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/ec/a926c293c605fa75e9cfb09f1e4840098ed46d2edaa6e2152ee35dc01ed3/numpy-2.3.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992", size = 6736652, upload-time = "2025-06-21T12:22:33.629Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/62/d68e52fb6fde5586650d4c0ce0b05ff3a48ad4df4ffd1b8866479d1d671d/numpy-2.3.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c", size = 14331561, upload-time = "2025-06-21T12:22:55.056Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/ec/b74d3f2430960044bdad6900d9f5edc2dc0fb8bf5a0be0f65287bf2cbe27/numpy-2.3.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48", size = 16693349, upload-time = "2025-06-21T12:23:20.53Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/15/def96774b9d7eb198ddadfcbd20281b20ebb510580419197e225f5c55c3e/numpy-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee", size = 15642053, upload-time = "2025-06-21T12:23:43.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/57/c3203974762a759540c6ae71d0ea2341c1fa41d84e4971a8e76d7141678a/numpy-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280", size = 18434184, upload-time = "2025-06-21T12:24:10.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/8a/ccdf201457ed8ac6245187850aff4ca56a79edbea4829f4e9f14d46fa9a5/numpy-2.3.1-cp313-cp313t-win32.whl", hash = "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e", size = 6440678, upload-time = "2025-06-21T12:24:21.596Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/7e/7f431d8bd8eb7e03d79294aed238b1b0b174b3148570d03a8a8a8f6a0da9/numpy-2.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc", size = 12870697, upload-time = "2025-06-21T12:24:40.644Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/ca/af82bf0fad4c3e573c6930ed743b5308492ff19917c7caaf2f9b6f9e2e98/numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244", size = 10260376, upload-time = "2025-06-21T12:24:56.884Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cublas-cu12"
|
||||
version = "12.6.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/af/eb/ff4b8c503fa1f1796679dce648854d58751982426e4e4b37d6fce49d259c/nvidia_cublas_cu12-12.6.4.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08ed2686e9875d01b58e3cb379c6896df8e76c75e0d4a7f7dace3d7b6d9ef8eb", size = 393138322, upload-time = "2024-11-20T17:40:25.65Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cuda-cupti-cu12"
|
||||
version = "12.6.80"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/49/60/7b6497946d74bcf1de852a21824d63baad12cd417db4195fc1bfe59db953/nvidia_cuda_cupti_cu12-12.6.80-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6768bad6cab4f19e8292125e5f1ac8aa7d1718704012a0e3272a6f61c4bce132", size = 8917980, upload-time = "2024-11-20T17:36:04.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/24/120ee57b218d9952c379d1e026c4479c9ece9997a4fb46303611ee48f038/nvidia_cuda_cupti_cu12-12.6.80-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a3eff6cdfcc6a4c35db968a06fcadb061cbc7d6dde548609a941ff8701b98b73", size = 8917972, upload-time = "2024-10-01T16:58:06.036Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cuda-nvrtc-cu12"
|
||||
version = "12.6.77"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/75/2e/46030320b5a80661e88039f59060d1790298b4718944a65a7f2aeda3d9e9/nvidia_cuda_nvrtc_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:35b0cc6ee3a9636d5409133e79273ce1f3fd087abb0532d2d2e8fff1fe9efc53", size = 23650380, upload-time = "2024-10-01T17:00:14.643Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cuda-runtime-cu12"
|
||||
version = "12.6.77"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/23/e717c5ac26d26cf39a27fbc076240fad2e3b817e5889d671b67f4f9f49c5/nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba3b56a4f896141e25e19ab287cd71e52a6a0f4b29d0d31609f60e3b4d5219b7", size = 897690, upload-time = "2024-11-20T17:35:30.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/62/65c05e161eeddbafeca24dc461f47de550d9fa8a7e04eb213e32b55cfd99/nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a84d15d5e1da416dd4774cb42edf5e954a3e60cc945698dc1d5be02321c44dc8", size = 897678, upload-time = "2024-10-01T16:57:33.821Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cudnn-cu12"
|
||||
version = "9.5.1.17"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-cublas-cu12" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/78/4535c9c7f859a64781e43c969a3a7e84c54634e319a996d43ef32ce46f83/nvidia_cudnn_cu12-9.5.1.17-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:30ac3869f6db17d170e0e556dd6cc5eee02647abc31ca856634d5a40f82c15b2", size = 570988386, upload-time = "2024-10-25T19:54:26.39Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cufft-cu12"
|
||||
version = "11.3.0.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-nvjitlink-cu12" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/16/73727675941ab8e6ffd86ca3a4b7b47065edcca7a997920b831f8147c99d/nvidia_cufft_cu12-11.3.0.4-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ccba62eb9cef5559abd5e0d54ceed2d9934030f51163df018532142a8ec533e5", size = 200221632, upload-time = "2024-11-20T17:41:32.357Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/de/99ec247a07ea40c969d904fc14f3a356b3e2a704121675b75c366b694ee1/nvidia_cufft_cu12-11.3.0.4-py3-none-manylinux2014_x86_64.whl", hash = "sha256:768160ac89f6f7b459bee747e8d175dbf53619cfe74b2a5636264163138013ca", size = 200221622, upload-time = "2024-10-01T17:03:58.79Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cufile-cu12"
|
||||
version = "1.11.1.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/66/cc9876340ac68ae71b15c743ddb13f8b30d5244af344ec8322b449e35426/nvidia_cufile_cu12-1.11.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc23469d1c7e52ce6c1d55253273d32c565dd22068647f3aa59b3c6b005bf159", size = 1142103, upload-time = "2024-11-20T17:42:11.83Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-curand-cu12"
|
||||
version = "10.3.7.77"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/73/1b/44a01c4e70933637c93e6e1a8063d1e998b50213a6b65ac5a9169c47e98e/nvidia_curand_cu12-10.3.7.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a42cd1344297f70b9e39a1e4f467a4e1c10f1da54ff7a85c12197f6c652c8bdf", size = 56279010, upload-time = "2024-11-20T17:42:50.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/aa/2c7ff0b5ee02eaef890c0ce7d4f74bc30901871c5e45dee1ae6d0083cd80/nvidia_curand_cu12-10.3.7.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:99f1a32f1ac2bd134897fc7a203f779303261268a65762a623bf30cc9fe79117", size = 56279000, upload-time = "2024-10-01T17:04:45.274Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cusolver-cu12"
|
||||
version = "11.7.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-cublas-cu12" },
|
||||
{ name = "nvidia-cusparse-cu12" },
|
||||
{ name = "nvidia-nvjitlink-cu12" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/6e/c2cf12c9ff8b872e92b4a5740701e51ff17689c4d726fca91875b07f655d/nvidia_cusolver_cu12-11.7.1.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e9e49843a7707e42022babb9bcfa33c29857a93b88020c4e4434656a655b698c", size = 158229790, upload-time = "2024-11-20T17:43:43.211Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/81/baba53585da791d043c10084cf9553e074548408e04ae884cfe9193bd484/nvidia_cusolver_cu12-11.7.1.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6cf28f17f64107a0c4d7802be5ff5537b2130bfc112f25d5a30df227058ca0e6", size = 158229780, upload-time = "2024-10-01T17:05:39.875Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cusparse-cu12"
|
||||
version = "12.5.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-nvjitlink-cu12" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/06/1e/b8b7c2f4099a37b96af5c9bb158632ea9e5d9d27d7391d7eb8fc45236674/nvidia_cusparse_cu12-12.5.4.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7556d9eca156e18184b94947ade0fba5bb47d69cec46bf8660fd2c71a4b48b73", size = 216561367, upload-time = "2024-11-20T17:44:54.824Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/ac/64c4316ba163e8217a99680c7605f779accffc6a4bcd0c778c12948d3707/nvidia_cusparse_cu12-12.5.4.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:23749a6571191a215cb74d1cdbff4a86e7b19f1200c071b3fcf844a5bea23a2f", size = 216561357, upload-time = "2024-10-01T17:06:29.861Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-cusparselt-cu12"
|
||||
version = "0.6.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/9a/72ef35b399b0e183bc2e8f6f558036922d453c4d8237dab26c666a04244b/nvidia_cusparselt_cu12-0.6.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:e5c8a26c36445dd2e6812f1177978a24e2d37cacce7e090f297a688d1ec44f46", size = 156785796, upload-time = "2024-10-15T21:29:17.709Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-nccl-cu12"
|
||||
version = "2.26.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/67/ca/f42388aed0fddd64ade7493dbba36e1f534d4e6fdbdd355c6a90030ae028/nvidia_nccl_cu12-2.26.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:694cf3879a206553cc9d7dbda76b13efaf610fdb70a50cba303de1b0d1530ac6", size = 201319755, upload-time = "2025-03-13T00:29:55.296Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-nvjitlink-cu12"
|
||||
version = "12.6.85"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/d7/c5383e47c7e9bf1c99d5bd2a8c935af2b6d705ad831a7ec5c97db4d82f4f/nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a", size = 19744971, upload-time = "2024-11-20T17:46:53.366Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvidia-nvtx-cu12"
|
||||
version = "12.6.77"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/56/9a/fff8376f8e3d084cd1530e1ef7b879bb7d6d265620c95c1b322725c694f4/nvidia_nvtx_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b90bed3df379fa79afbd21be8e04a0314336b8ae16768b58f2d34cb1d04cd7d2", size = 89276, upload-time = "2024-11-20T17:38:27.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/4e/0d0c945463719429b7bd21dece907ad0bde437a2ff12b9b12fee94722ab0/nvidia_nvtx_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6574241a3ec5fdc9334353ab8c479fe75841dbe8f4532a8fc97ce63503330ba1", size = 89265, upload-time = "2024-10-01T17:00:38.172Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "onnx"
|
||||
version = "1.18.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
{ name = "protobuf" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3d/60/e56e8ec44ed34006e6d4a73c92a04d9eea6163cc12440e35045aec069175/onnx-1.18.0.tar.gz", hash = "sha256:3d8dbf9e996629131ba3aa1afd1d8239b660d1f830c6688dd7e03157cccd6b9c", size = 12563009, upload-time = "2025-05-12T22:03:09.626Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/fe/16228aca685392a7114625b89aae98b2dc4058a47f0f467a376745efe8d0/onnx-1.18.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:521bac578448667cbb37c50bf05b53c301243ede8233029555239930996a625b", size = 18285770, upload-time = "2025-05-12T22:02:26.116Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/77/ba50a903a9b5e6f9be0fa50f59eb2fca4a26ee653375408fbc72c3acbf9f/onnx-1.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4da451bf1c5ae381f32d430004a89f0405bc57a8471b0bddb6325a5b334aa40", size = 17421291, upload-time = "2025-05-12T22:02:29.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/23/25ec2ba723ac62b99e8fed6d7b59094dadb15e38d4c007331cc9ae3dfa5f/onnx-1.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99afac90b4cdb1471432203c3c1f74e16549c526df27056d39f41a9a47cfb4af", size = 17584084, upload-time = "2025-05-12T22:02:32.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/4d/2c253a36070fb43f340ff1d2c450df6a9ef50b938adcd105693fee43c4ee/onnx-1.18.0-cp312-cp312-win32.whl", hash = "sha256:ee159b41a3ae58d9c7341cf432fc74b96aaf50bd7bb1160029f657b40dc69715", size = 15734892, upload-time = "2025-05-12T22:02:35.527Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/92/048ba8fafe6b2b9a268ec2fb80def7e66c0b32ab2cae74de886981f05a27/onnx-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:102c04edc76b16e9dfeda5a64c1fccd7d3d2913b1544750c01d38f1ac3c04e05", size = 15850336, upload-time = "2025-05-12T22:02:38.545Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/66/bbc4ffedd44165dcc407a51ea4c592802a5391ce3dc94aa5045350f64635/onnx-1.18.0-cp312-cp312-win_arm64.whl", hash = "sha256:911b37d724a5d97396f3c2ef9ea25361c55cbc9aa18d75b12a52b620b67145af", size = 15823802, upload-time = "2025-05-12T22:02:42.037Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/da/9fb8824513fae836239276870bfcc433fa2298d34ed282c3a47d3962561b/onnx-1.18.0-cp313-cp313-macosx_12_0_universal2.whl", hash = "sha256:030d9f5f878c5f4c0ff70a4545b90d7812cd6bfe511de2f3e469d3669c8cff95", size = 18285906, upload-time = "2025-05-12T22:02:45.01Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/e8/762b5fb5ed1a2b8e9a4bc5e668c82723b1b789c23b74e6b5a3356731ae4e/onnx-1.18.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8521544987d713941ee1e591520044d35e702f73dc87e91e6d4b15a064ae813d", size = 17421486, upload-time = "2025-05-12T22:02:48.467Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/bb/471da68df0364f22296456c7f6becebe0a3da1ba435cdb371099f516da6e/onnx-1.18.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c137eecf6bc618c2f9398bcc381474b55c817237992b169dfe728e169549e8f", size = 17583581, upload-time = "2025-05-12T22:02:51.784Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/0d/01a95edc2cef6ad916e04e8e1267a9286f15b55c90cce5d3cdeb359d75d6/onnx-1.18.0-cp313-cp313-win32.whl", hash = "sha256:6c093ffc593e07f7e33862824eab9225f86aa189c048dd43ffde207d7041a55f", size = 15734621, upload-time = "2025-05-12T22:02:54.62Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/95/253451a751be32b6173a648b68f407188009afa45cd6388780c330ff5d5d/onnx-1.18.0-cp313-cp313-win_amd64.whl", hash = "sha256:230b0fb615e5b798dc4a3718999ec1828360bc71274abd14f915135eab0255f1", size = 15850472, upload-time = "2025-05-12T22:02:57.54Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/b1/6fd41b026836df480a21687076e0f559bc3ceeac90f2be8c64b4a7a1f332/onnx-1.18.0-cp313-cp313-win_arm64.whl", hash = "sha256:6f91930c1a284135db0f891695a263fc876466bf2afbd2215834ac08f600cfca", size = 15823808, upload-time = "2025-05-12T22:03:00.305Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/f3/499e53dd41fa7302f914dd18543da01e0786a58b9a9d347497231192001f/onnx-1.18.0-cp313-cp313t-macosx_12_0_universal2.whl", hash = "sha256:2f4d37b0b5c96a873887652d1cbf3f3c70821b8c66302d84b0f0d89dd6e47653", size = 18316526, upload-time = "2025-05-12T22:03:03.691Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/dd/6abe5d7bd23f5ed3ade8352abf30dff1c7a9e97fc1b0a17b5d7c726e98a9/onnx-1.18.0-cp313-cp313t-win_amd64.whl", hash = "sha256:a69afd0baa372162948b52c13f3aa2730123381edf926d7ef3f68ca7cec6d0d0", size = 15865055, upload-time = "2025-05-12T22:03:06.663Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "onnx-ir"
|
||||
version = "0.1.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "ml-dtypes" },
|
||||
{ name = "numpy" },
|
||||
{ name = "onnx" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2a/2a/92caa778bf1bcaa5dce502d3f9ae9c026a3e8b002f464db3bcd26a32b839/onnx_ir-0.1.5.tar.gz", hash = "sha256:0182e679ea7125d7d3a4600c10df69576a67224ab6ef0cdbf20425c3ef5c8d8d", size = 106648, upload-time = "2025-08-08T17:06:18.391Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/16/80/4810ea8f8e5394995b65f13676b3d9dbbcce36ce4c6bd5b62ea8252cc22e/onnx_ir-0.1.5-py3-none-any.whl", hash = "sha256:f7e58098e470d796bc22e2732f09422c6f5f7432f6b81ef3d1e1921c97fcd3fe", size = 120678, upload-time = "2025-08-08T17:06:17.164Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "onnxscript"
|
||||
version = "0.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "ml-dtypes" },
|
||||
{ name = "numpy" },
|
||||
{ name = "onnx" },
|
||||
{ name = "onnx-ir" },
|
||||
{ name = "packaging" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fd/8e/1bb4821b4bd1e52c8be6a9edb3fd787875660caa3b0816fcb3e1eafb3568/onnxscript-0.3.2.tar.gz", hash = "sha256:60820d4c3e39f8ea7d945dd4f96fa5dd23c3c2e111022512477c52c9e78eb3d4", size = 575968, upload-time = "2025-07-11T20:04:19.683Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/88/008f82aca27fd6240d12d3084d24852f586cef2ccf2fb07612185fbb71f6/onnxscript-0.3.2-py3-none-any.whl", hash = "sha256:220bbecccae228a285bd385159c47a09f003c623c9636afd56cc91df50706a88", size = 667405, upload-time = "2025-07-11T20:04:22.036Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "25.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pandas"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "pytz" },
|
||||
{ name = "tzdata" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/51/48f713c4c728d7c55ef7444ba5ea027c26998d96d1a40953b346438602fc/pandas-2.3.0.tar.gz", hash = "sha256:34600ab34ebf1131a7613a260a61dbe8b62c188ec0ea4c296da7c9a06b004133", size = 4484490, upload-time = "2025-06-05T03:27:54.133Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/94/46/24192607058dd607dbfacdd060a2370f6afb19c2ccb617406469b9aeb8e7/pandas-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2eb4728a18dcd2908c7fccf74a982e241b467d178724545a48d0caf534b38ebf", size = 11573865, upload-time = "2025-06-05T03:26:46.774Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/cc/ae8ea3b800757a70c9fdccc68b67dc0280a6e814efcf74e4211fd5dea1ca/pandas-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9d8c3187be7479ea5c3d30c32a5d73d62a621166675063b2edd21bc47614027", size = 10702154, upload-time = "2025-06-05T16:50:14.439Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/ba/a7883d7aab3d24c6540a2768f679e7414582cc389876d469b40ec749d78b/pandas-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ff730713d4c4f2f1c860e36c005c7cefc1c7c80c21c0688fd605aa43c9fcf09", size = 11262180, upload-time = "2025-06-05T16:50:17.453Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/a5/931fc3ad333d9d87b10107d948d757d67ebcfc33b1988d5faccc39c6845c/pandas-2.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba24af48643b12ffe49b27065d3babd52702d95ab70f50e1b34f71ca703e2c0d", size = 11991493, upload-time = "2025-06-05T03:26:51.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/bf/0213986830a92d44d55153c1d69b509431a972eb73f204242988c4e66e86/pandas-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:404d681c698e3c8a40a61d0cd9412cc7364ab9a9cc6e144ae2992e11a2e77a20", size = 12470733, upload-time = "2025-06-06T00:00:18.651Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/0e/21eb48a3a34a7d4bac982afc2c4eb5ab09f2d988bdf29d92ba9ae8e90a79/pandas-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6021910b086b3ca756755e86ddc64e0ddafd5e58e076c72cb1585162e5ad259b", size = 13212406, upload-time = "2025-06-05T03:26:55.992Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/d9/74017c4eec7a28892d8d6e31ae9de3baef71f5a5286e74e6b7aad7f8c837/pandas-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:094e271a15b579650ebf4c5155c05dcd2a14fd4fdd72cf4854b2f7ad31ea30be", size = 10976199, upload-time = "2025-06-05T03:26:59.594Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/57/5cb75a56a4842bbd0511c3d1c79186d8315b82dac802118322b2de1194fe/pandas-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c7e2fc25f89a49a11599ec1e76821322439d90820108309bf42130d2f36c983", size = 11518913, upload-time = "2025-06-05T03:27:02.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/01/0c8785610e465e4948a01a059562176e4c8088aa257e2e074db868f86d4e/pandas-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6da97aeb6a6d233fb6b17986234cc723b396b50a3c6804776351994f2a658fd", size = 10655249, upload-time = "2025-06-05T16:50:20.17Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/6a/47fd7517cd8abe72a58706aab2b99e9438360d36dcdb052cf917b7bf3bdc/pandas-2.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb32dc743b52467d488e7a7c8039b821da2826a9ba4f85b89ea95274f863280f", size = 11328359, upload-time = "2025-06-05T03:27:06.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/b3/463bfe819ed60fb7e7ddffb4ae2ee04b887b3444feee6c19437b8f834837/pandas-2.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:213cd63c43263dbb522c1f8a7c9d072e25900f6975596f883f4bebd77295d4f3", size = 12024789, upload-time = "2025-06-05T03:27:09.875Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/0c/e0704ccdb0ac40aeb3434d1c641c43d05f75c92e67525df39575ace35468/pandas-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1d2b33e68d0ce64e26a4acc2e72d747292084f4e8db4c847c6f5f6cbe56ed6d8", size = 12480734, upload-time = "2025-06-06T00:00:22.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/df/815d6583967001153bb27f5cf075653d69d51ad887ebbf4cfe1173a1ac58/pandas-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:430a63bae10b5086995db1b02694996336e5a8ac9a96b4200572b413dfdfccb9", size = 13223381, upload-time = "2025-06-05T03:27:15.641Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/88/ca5973ed07b7f484c493e941dbff990861ca55291ff7ac67c815ce347395/pandas-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4930255e28ff5545e2ca404637bcc56f031893142773b3468dc021c6c32a1390", size = 10970135, upload-time = "2025-06-05T03:27:24.131Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/fb/0994c14d1f7909ce83f0b1fb27958135513c4f3f2528bde216180aa73bfc/pandas-2.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f925f1ef673b4bd0271b1809b72b3270384f2b7d9d14a189b12b7fc02574d575", size = 12141356, upload-time = "2025-06-05T03:27:34.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/a2/9b903e5962134497ac4f8a96f862ee3081cb2506f69f8e4778ce3d9c9d82/pandas-2.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78ad363ddb873a631e92a3c063ade1ecfb34cae71e9a2be6ad100f875ac1042", size = 11474674, upload-time = "2025-06-05T03:27:39.448Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/3a/3806d041bce032f8de44380f866059437fb79e36d6b22c82c187e65f765b/pandas-2.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951805d146922aed8357e4cc5671b8b0b9be1027f0619cea132a9f3f65f2f09c", size = 11439876, upload-time = "2025-06-05T03:27:43.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/aa/3fc3181d12b95da71f5c2537c3e3b3af6ab3a8c392ab41ebb766e0929bc6/pandas-2.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a881bc1309f3fce34696d07b00f13335c41f5f5a8770a33b09ebe23261cfc67", size = 11966182, upload-time = "2025-06-05T03:27:47.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/e7/e12f2d9b0a2c4a2cc86e2aabff7ccfd24f03e597d770abfa2acd313ee46b/pandas-2.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1991bbb96f4050b09b5f811253c4f3cf05ee89a589379aa36cd623f21a31d6f", size = 12547686, upload-time = "2025-06-06T00:00:26.142Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/c2/646d2e93e0af70f4e5359d870a63584dacbc324b54d73e6b3267920ff117/pandas-2.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bb3be958022198531eb7ec2008cfc78c5b1eed51af8600c6c5d9160d89d8d249", size = 13231847, upload-time = "2025-06-05T03:27:51.465Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "11.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707, upload-time = "2025-04-12T17:50:03.289Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/40/052610b15a1b8961f52537cc8326ca6a881408bc2bdad0d852edeb6ed33b/pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f", size = 3190185, upload-time = "2025-04-12T17:48:00.417Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/7e/b86dbd35a5f938632093dc40d1682874c33dcfe832558fc80ca56bfcb774/pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b", size = 3030306, upload-time = "2025-04-12T17:48:02.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/5c/467a161f9ed53e5eab51a42923c33051bf8d1a2af4626ac04f5166e58e0c/pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d", size = 4416121, upload-time = "2025-04-12T17:48:04.554Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/73/972b7742e38ae0e2ac76ab137ca6005dcf877480da0d9d61d93b613065b4/pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4", size = 4501707, upload-time = "2025-04-12T17:48:06.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/3a/427e4cb0b9e177efbc1a84798ed20498c4f233abde003c06d2650a6d60cb/pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d", size = 4522921, upload-time = "2025-04-12T17:48:09.229Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/7c/d8b1330458e4d2f3f45d9508796d7caf0c0d3764c00c823d10f6f1a3b76d/pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4", size = 4612523, upload-time = "2025-04-12T17:48:11.631Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/2f/65738384e0b1acf451de5a573d8153fe84103772d139e1e0bdf1596be2ea/pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443", size = 4587836, upload-time = "2025-04-12T17:48:13.592Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/c5/e795c9f2ddf3debb2dedd0df889f2fe4b053308bb59a3cc02a0cd144d641/pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c", size = 4669390, upload-time = "2025-04-12T17:48:15.938Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/ae/ca0099a3995976a9fce2f423166f7bff9b12244afdc7520f6ed38911539a/pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3", size = 2332309, upload-time = "2025-04-12T17:48:17.885Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/18/24bff2ad716257fc03da964c5e8f05d9790a779a8895d6566e493ccf0189/pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941", size = 2676768, upload-time = "2025-04-12T17:48:19.655Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/bb/e8d656c9543276517ee40184aaa39dcb41e683bca121022f9323ae11b39d/pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb", size = 2415087, upload-time = "2025-04-12T17:48:21.991Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/9c/447528ee3776e7ab8897fe33697a7ff3f0475bb490c5ac1456a03dc57956/pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28", size = 3190098, upload-time = "2025-04-12T17:48:23.915Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166, upload-time = "2025-04-12T17:48:25.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674, upload-time = "2025-04-12T17:48:27.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/5f/cbe509c0ddf91cc3a03bbacf40e5c2339c4912d16458fcb797bb47bcb269/pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1", size = 4496005, upload-time = "2025-04-12T17:48:29.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/b3/dd4338d8fb8a5f312021f2977fb8198a1184893f9b00b02b75d565c33b51/pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f", size = 4518707, upload-time = "2025-04-12T17:48:31.874Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/eb/2552ecebc0b887f539111c2cd241f538b8ff5891b8903dfe672e997529be/pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155", size = 4610008, upload-time = "2025-04-12T17:48:34.422Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/d1/924ce51bea494cb6e7959522d69d7b1c7e74f6821d84c63c3dc430cbbf3b/pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14", size = 4585420, upload-time = "2025-04-12T17:48:37.641Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/ab/8f81312d255d713b99ca37479a4cb4b0f48195e530cdc1611990eb8fd04b/pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b", size = 4667655, upload-time = "2025-04-12T17:48:39.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/86/8f2e9d2dc3d308dfd137a07fe1cc478df0a23d42a6c4093b087e738e4827/pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2", size = 2332329, upload-time = "2025-04-12T17:48:41.765Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/ec/1179083b8d6067a613e4d595359b5fdea65d0a3b7ad623fee906e1b3c4d2/pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691", size = 2676388, upload-time = "2025-04-12T17:48:43.625Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/f1/2fc1e1e294de897df39fa8622d829b8828ddad938b0eaea256d65b84dd72/pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c", size = 2414950, upload-time = "2025-04-12T17:48:45.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/3e/c328c48b3f0ead7bab765a84b4977acb29f101d10e4ef57a5e3400447c03/pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22", size = 3192759, upload-time = "2025-04-12T17:48:47.866Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/0e/1c68532d833fc8b9f404d3a642991441d9058eccd5606eab31617f29b6d4/pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7", size = 3033284, upload-time = "2025-04-12T17:48:50.189Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/cb/6faf3fb1e7705fd2db74e070f3bf6f88693601b0ed8e81049a8266de4754/pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16", size = 4445826, upload-time = "2025-04-12T17:48:52.346Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/94/8be03d50b70ca47fb434a358919d6a8d6580f282bbb7af7e4aa40103461d/pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b", size = 4527329, upload-time = "2025-04-12T17:48:54.403Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/a4/bfe78777076dc405e3bd2080bc32da5ab3945b5a25dc5d8acaa9de64a162/pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406", size = 4549049, upload-time = "2025-04-12T17:48:56.383Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/4d/eaf9068dc687c24979e977ce5677e253624bd8b616b286f543f0c1b91662/pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91", size = 4635408, upload-time = "2025-04-12T17:48:58.782Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/26/0fd443365d9c63bc79feb219f97d935cd4b93af28353cba78d8e77b61719/pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751", size = 4614863, upload-time = "2025-04-12T17:49:00.709Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/65/dca4d2506be482c2c6641cacdba5c602bc76d8ceb618fd37de855653a419/pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9", size = 4692938, upload-time = "2025-04-12T17:49:02.946Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/92/1ca0c3f09233bd7decf8f7105a1c4e3162fb9142128c74adad0fb361b7eb/pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd", size = 2335774, upload-time = "2025-04-12T17:49:04.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/ac/77525347cb43b83ae905ffe257bbe2cc6fd23acb9796639a1f56aa59d191/pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e", size = 2681895, upload-time = "2025-04-12T17:49:06.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/32/32dc030cfa91ca0fc52baebbba2e009bb001122a1daa8b6a79ad830b38d3/pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681", size = 2417234, upload-time = "2025-04-12T17:49:08.399Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "protobuf"
|
||||
version = "6.31.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/52/f3/b9655a711b32c19720253f6f06326faf90580834e2e83f840472d752bc8b/protobuf-6.31.1.tar.gz", hash = "sha256:d8cac4c982f0b957a4dc73a80e2ea24fab08e679c0de9deb835f4a12d69aca9a", size = 441797, upload-time = "2025-05-28T19:25:54.947Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/6f/6ab8e4bf962fd5570d3deaa2d5c38f0a363f57b4501047b5ebeb83ab1125/protobuf-6.31.1-cp310-abi3-win32.whl", hash = "sha256:7fa17d5a29c2e04b7d90e5e32388b8bfd0e7107cd8e616feef7ed3fa6bdab5c9", size = 423603, upload-time = "2025-05-28T19:25:41.198Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/3a/b15c4347dd4bf3a1b0ee882f384623e2063bb5cf9fa9d57990a4f7df2fb6/protobuf-6.31.1-cp310-abi3-win_amd64.whl", hash = "sha256:426f59d2964864a1a366254fa703b8632dcec0790d8862d30034d8245e1cd447", size = 435283, upload-time = "2025-05-28T19:25:44.275Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/c9/b9689a2a250264a84e66c46d8862ba788ee7a641cdca39bccf64f59284b7/protobuf-6.31.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:6f1227473dc43d44ed644425268eb7c2e488ae245d51c6866d19fe158e207402", size = 425604, upload-time = "2025-05-28T19:25:45.702Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/a1/7a5a94032c83375e4fe7e7f56e3976ea6ac90c5e85fac8576409e25c39c3/protobuf-6.31.1-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:a40fc12b84c154884d7d4c4ebd675d5b3b5283e155f324049ae396b95ddebc39", size = 322115, upload-time = "2025-05-28T19:25:47.128Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/b1/b59d405d64d31999244643d88c45c8241c58f17cc887e73bcb90602327f8/protobuf-6.31.1-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:4ee898bf66f7a8b0bd21bce523814e6fbd8c6add948045ce958b73af7e8878c6", size = 321070, upload-time = "2025-05-28T19:25:50.036Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/af/ab3c51ab7507a7325e98ffe691d9495ee3d3aa5f589afad65ec920d39821/protobuf-6.31.1-py3-none-any.whl", hash = "sha256:720a6c7e6b77288b85063569baae8536671b39f15cc22037ec7045658d80489e", size = 168724, upload-time = "2025-05-28T19:25:53.926Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bb/22/f1129e69d94ffff626bdb5c835506b3a5b4f3d070f17ea295e12c2c6f60f/pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be", size = 1088608, upload-time = "2025-03-25T05:01:28.114Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120, upload-time = "2025-03-25T05:01:24.908Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.9.0.post0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "six" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2025.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scikit-learn"
|
||||
version = "1.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "joblib" },
|
||||
{ name = "numpy" },
|
||||
{ name = "scipy" },
|
||||
{ name = "threadpoolctl" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/3b/29fa87e76b1d7b3b77cc1fcbe82e6e6b8cd704410705b008822de530277c/scikit_learn-1.7.0.tar.gz", hash = "sha256:c01e869b15aec88e2cdb73d27f15bdbe03bce8e2fb43afbe77c45d399e73a5a3", size = 7178217, upload-time = "2025-06-05T22:02:46.703Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/70/3a/bffab14e974a665a3ee2d79766e7389572ffcaad941a246931c824afcdb2/scikit_learn-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c2c7243d34aaede0efca7a5a96d67fddaebb4ad7e14a70991b9abee9dc5c0379", size = 11646758, upload-time = "2025-06-05T22:02:09.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/d8/f3249232fa79a70cb40595282813e61453c1e76da3e1a44b77a63dd8d0cb/scikit_learn-1.7.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:9f39f6a811bf3f15177b66c82cbe0d7b1ebad9f190737dcdef77cfca1ea3c19c", size = 10673971, upload-time = "2025-06-05T22:02:12.217Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/93/eb14c50533bea2f77758abe7d60a10057e5f2e2cdcf0a75a14c6bc19c734/scikit_learn-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63017a5f9a74963d24aac7590287149a8d0f1a0799bbe7173c0d8ba1523293c0", size = 11818428, upload-time = "2025-06-05T22:02:14.947Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/17/804cc13b22a8663564bb0b55fb89e661a577e4e88a61a39740d58b909efe/scikit_learn-1.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b2f8a0b1e73e9a08b7cc498bb2aeab36cdc1f571f8ab2b35c6e5d1c7115d97d", size = 12505887, upload-time = "2025-06-05T22:02:17.824Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/c7/4e956281a077f4835458c3f9656c666300282d5199039f26d9de1dabd9be/scikit_learn-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:34cc8d9d010d29fb2b7cbcd5ccc24ffdd80515f65fe9f1e4894ace36b267ce19", size = 10668129, upload-time = "2025-06-05T22:02:20.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/c3/a85dcccdaf1e807e6f067fa95788a6485b0491d9ea44fd4c812050d04f45/scikit_learn-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5b7974f1f32bc586c90145df51130e02267e4b7e77cab76165c76cf43faca0d9", size = 11559841, upload-time = "2025-06-05T22:02:23.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/57/eea0de1562cc52d3196eae51a68c5736a31949a465f0b6bb3579b2d80282/scikit_learn-1.7.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:014e07a23fe02e65f9392898143c542a50b6001dbe89cb867e19688e468d049b", size = 10616463, upload-time = "2025-06-05T22:02:26.068Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/a4/39717ca669296dfc3a62928393168da88ac9d8cbec88b6321ffa62c6776f/scikit_learn-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e7ced20582d3a5516fb6f405fd1d254e1f5ce712bfef2589f51326af6346e8", size = 11766512, upload-time = "2025-06-05T22:02:28.689Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/cd/a19722241d5f7b51e08351e1e82453e0057aeb7621b17805f31fcb57bb6c/scikit_learn-1.7.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1babf2511e6ffd695da7a983b4e4d6de45dce39577b26b721610711081850906", size = 12461075, upload-time = "2025-06-05T22:02:31.233Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/bc/282514272815c827a9acacbe5b99f4f1a4bc5961053719d319480aee0812/scikit_learn-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:5abd2acff939d5bd4701283f009b01496832d50ddafa83c90125a4e41c33e314", size = 10652517, upload-time = "2025-06-05T22:02:34.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/78/7357d12b2e4c6674175f9a09a3ba10498cde8340e622715bcc71e532981d/scikit_learn-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e39d95a929b112047c25b775035c8c234c5ca67e681ce60d12413afb501129f7", size = 12111822, upload-time = "2025-06-05T22:02:36.904Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/0c/9c3715393343f04232f9d81fe540eb3831d0b4ec351135a145855295110f/scikit_learn-1.7.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:0521cb460426c56fee7e07f9365b0f45ec8ca7b2d696534ac98bfb85e7ae4775", size = 11325286, upload-time = "2025-06-05T22:02:39.739Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/e0/42282ad3dd70b7c1a5f65c412ac3841f6543502a8d6263cae7b466612dc9/scikit_learn-1.7.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:317ca9f83acbde2883bd6bb27116a741bfcb371369706b4f9973cf30e9a03b0d", size = 12380865, upload-time = "2025-06-05T22:02:42.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/d0/3ef4ab2c6be4aa910445cd09c5ef0b44512e3de2cfb2112a88bb647d2cf7/scikit_learn-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:126c09740a6f016e815ab985b21e3a0656835414521c81fc1a8da78b679bdb75", size = 11549609, upload-time = "2025-06-05T22:02:44.483Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/81/18/b06a83f0c5ee8cddbde5e3f3d0bb9b702abfa5136ef6d4620ff67df7eee5/scipy-1.16.0.tar.gz", hash = "sha256:b5ef54021e832869c8cfb03bc3bf20366cbcd426e02a58e8a58d7584dfbb8f62", size = 30581216, upload-time = "2025-06-22T16:27:55.782Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/01/c0/c943bc8d2bbd28123ad0f4f1eef62525fa1723e84d136b32965dcb6bad3a/scipy-1.16.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:7eb6bd33cef4afb9fa5f1fb25df8feeb1e52d94f21a44f1d17805b41b1da3180", size = 36459071, upload-time = "2025-06-22T16:19:06.605Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/0d/270e2e9f1a4db6ffbf84c9a0b648499842046e4e0d9b2275d150711b3aba/scipy-1.16.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:1dbc8fdba23e4d80394ddfab7a56808e3e6489176d559c6c71935b11a2d59db1", size = 28490500, upload-time = "2025-06-22T16:19:11.775Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/22/01d7ddb07cff937d4326198ec8d10831367a708c3da72dfd9b7ceaf13028/scipy-1.16.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:7dcf42c380e1e3737b343dec21095c9a9ad3f9cbe06f9c05830b44b1786c9e90", size = 20762345, upload-time = "2025-06-22T16:19:15.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/7f/87fd69856569ccdd2a5873fe5d7b5bbf2ad9289d7311d6a3605ebde3a94b/scipy-1.16.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:26ec28675f4a9d41587266084c626b02899db373717d9312fa96ab17ca1ae94d", size = 23418563, upload-time = "2025-06-22T16:19:20.746Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/f1/e4f4324fef7f54160ab749efbab6a4bf43678a9eb2e9817ed71a0a2fd8de/scipy-1.16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:952358b7e58bd3197cfbd2f2f2ba829f258404bdf5db59514b515a8fe7a36c52", size = 33203951, upload-time = "2025-06-22T16:19:25.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/f0/b6ac354a956384fd8abee2debbb624648125b298f2c4a7b4f0d6248048a5/scipy-1.16.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03931b4e870c6fef5b5c0970d52c9f6ddd8c8d3e934a98f09308377eba6f3824", size = 35070225, upload-time = "2025-06-22T16:19:31.416Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/73/5cbe4a3fd4bc3e2d67ffad02c88b83edc88f381b73ab982f48f3df1a7790/scipy-1.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:512c4f4f85912767c351a0306824ccca6fd91307a9f4318efe8fdbd9d30562ef", size = 35389070, upload-time = "2025-06-22T16:19:37.387Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/e8/a60da80ab9ed68b31ea5a9c6dfd3c2f199347429f229bf7f939a90d96383/scipy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e69f798847e9add03d512eaf5081a9a5c9a98757d12e52e6186ed9681247a1ac", size = 37825287, upload-time = "2025-06-22T16:19:43.375Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/b5/29fece1a74c6a94247f8a6fb93f5b28b533338e9c34fdcc9cfe7a939a767/scipy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:adf9b1999323ba335adc5d1dc7add4781cb5a4b0ef1e98b79768c05c796c4e49", size = 38431929, upload-time = "2025-06-22T16:19:49.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/95/0746417bc24be0c2a7b7563946d61f670a3b491b76adede420e9d173841f/scipy-1.16.0-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:e9f414cbe9ca289a73e0cc92e33a6a791469b6619c240aa32ee18abdce8ab451", size = 36418162, upload-time = "2025-06-22T16:19:56.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/5a/914355a74481b8e4bbccf67259bbde171348a3f160b67b4945fbc5f5c1e5/scipy-1.16.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:bbba55fb97ba3cdef9b1ee973f06b09d518c0c7c66a009c729c7d1592be1935e", size = 28465985, upload-time = "2025-06-22T16:20:01.238Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/46/63477fc1246063855969cbefdcee8c648ba4b17f67370bd542ba56368d0b/scipy-1.16.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:58e0d4354eacb6004e7aa1cd350e5514bd0270acaa8d5b36c0627bb3bb486974", size = 20737961, upload-time = "2025-06-22T16:20:05.913Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/86/0fbb5588b73555e40f9d3d6dde24ee6fac7d8e301a27f6f0cab9d8f66ff2/scipy-1.16.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:75b2094ec975c80efc273567436e16bb794660509c12c6a31eb5c195cbf4b6dc", size = 23377941, upload-time = "2025-06-22T16:20:10.668Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/80/a561f2bf4c2da89fa631b3cbf31d120e21ea95db71fd9ec00cb0247c7a93/scipy-1.16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b65d232157a380fdd11a560e7e21cde34fdb69d65c09cb87f6cc024ee376351", size = 33196703, upload-time = "2025-06-22T16:20:16.097Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/6b/3443abcd0707d52e48eb315e33cc669a95e29fc102229919646f5a501171/scipy-1.16.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1d8747f7736accd39289943f7fe53a8333be7f15a82eea08e4afe47d79568c32", size = 35083410, upload-time = "2025-06-22T16:20:21.734Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/ab/eb0fc00e1e48961f1bd69b7ad7e7266896fe5bad4ead91b5fc6b3561bba4/scipy-1.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eb9f147a1b8529bb7fec2a85cf4cf42bdfadf9e83535c309a11fdae598c88e8b", size = 35387829, upload-time = "2025-06-22T16:20:27.548Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/9e/d6fc64e41fad5d481c029ee5a49eefc17f0b8071d636a02ceee44d4a0de2/scipy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d2b83c37edbfa837a8923d19c749c1935ad3d41cf196006a24ed44dba2ec4358", size = 37841356, upload-time = "2025-06-22T16:20:35.112Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/a7/4c94bbe91f12126b8bf6709b2471900577b7373a4fd1f431f28ba6f81115/scipy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:79a3c13d43c95aa80b87328a46031cf52508cf5f4df2767602c984ed1d3c6bbe", size = 38403710, upload-time = "2025-06-22T16:21:54.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/20/965da8497f6226e8fa90ad3447b82ed0e28d942532e92dd8b91b43f100d4/scipy-1.16.0-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:f91b87e1689f0370690e8470916fe1b2308e5b2061317ff76977c8f836452a47", size = 36813833, upload-time = "2025-06-22T16:20:43.925Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/f4/197580c3dac2d234e948806e164601c2df6f0078ed9f5ad4a62685b7c331/scipy-1.16.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:88a6ca658fb94640079e7a50b2ad3b67e33ef0f40e70bdb7dc22017dae73ac08", size = 28974431, upload-time = "2025-06-22T16:20:51.302Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/fc/e18b8550048d9224426e76906694c60028dbdb65d28b1372b5503914b89d/scipy-1.16.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ae902626972f1bd7e4e86f58fd72322d7f4ec7b0cfc17b15d4b7006efc385176", size = 21246454, upload-time = "2025-06-22T16:20:57.276Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/48/07b97d167e0d6a324bfd7484cd0c209cc27338b67e5deadae578cf48e809/scipy-1.16.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:8cb824c1fc75ef29893bc32b3ddd7b11cf9ab13c1127fe26413a05953b8c32ed", size = 23772979, upload-time = "2025-06-22T16:21:03.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/4f/9efbd3f70baf9582edf271db3002b7882c875ddd37dc97f0f675ad68679f/scipy-1.16.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:de2db7250ff6514366a9709c2cba35cb6d08498e961cba20d7cff98a7ee88938", size = 33341972, upload-time = "2025-06-22T16:21:11.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/dc/9e496a3c5dbe24e76ee24525155ab7f659c20180bab058ef2c5fa7d9119c/scipy-1.16.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e85800274edf4db8dd2e4e93034f92d1b05c9421220e7ded9988b16976f849c1", size = 35185476, upload-time = "2025-06-22T16:21:19.156Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/b3/21001cff985a122ba434c33f2c9d7d1dc3b669827e94f4fc4e1fe8b9dfd8/scipy-1.16.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4f720300a3024c237ace1cb11f9a84c38beb19616ba7c4cdcd771047a10a1706", size = 35570990, upload-time = "2025-06-22T16:21:27.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/d3/7ba42647d6709251cdf97043d0c107e0317e152fa2f76873b656b509ff55/scipy-1.16.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:aad603e9339ddb676409b104c48a027e9916ce0d2838830691f39552b38a352e", size = 37950262, upload-time = "2025-06-22T16:21:36.976Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/c4/231cac7a8385394ebbbb4f1ca662203e9d8c332825ab4f36ffc3ead09a42/scipy-1.16.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f56296fefca67ba605fd74d12f7bd23636267731a72cb3947963e76b8c0a25db", size = 38515076, upload-time = "2025-06-22T16:21:45.694Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "seaborn"
|
||||
version = "0.13.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "matplotlib" },
|
||||
{ name = "numpy" },
|
||||
{ name = "pandas" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "80.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sympy"
|
||||
version = "1.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mpmath" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "threadpoolctl"
|
||||
version = "3.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "torch"
|
||||
version = "2.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "filelock" },
|
||||
{ name = "fsspec" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "networkx" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cufile-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusparselt-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "setuptools" },
|
||||
{ name = "sympy" },
|
||||
{ name = "triton", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/87/93/fb505a5022a2e908d81fe9a5e0aa84c86c0d5f408173be71c6018836f34e/torch-2.7.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:27ea1e518df4c9de73af7e8a720770f3628e7f667280bce2be7a16292697e3fa", size = 98948276, upload-time = "2025-06-04T17:39:12.852Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/56/7e/67c3fe2b8c33f40af06326a3d6ae7776b3e3a01daa8f71d125d78594d874/torch-2.7.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c33360cfc2edd976c2633b3b66c769bdcbbf0e0b6550606d188431c81e7dd1fc", size = 821025792, upload-time = "2025-06-04T17:34:58.747Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/37/a37495502bc7a23bf34f89584fa5a78e25bae7b8da513bc1b8f97afb7009/torch-2.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:d8bf6e1856ddd1807e79dc57e54d3335f2b62e6f316ed13ed3ecfe1fc1df3d8b", size = 216050349, upload-time = "2025-06-04T17:38:59.709Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/60/04b77281c730bb13460628e518c52721257814ac6c298acd25757f6a175c/torch-2.7.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:787687087412c4bd68d315e39bc1223f08aae1d16a9e9771d95eabbb04ae98fb", size = 68645146, upload-time = "2025-06-04T17:38:52.97Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/81/e48c9edb655ee8eb8c2a6026abdb6f8d2146abd1f150979ede807bb75dcb/torch-2.7.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:03563603d931e70722dce0e11999d53aa80a375a3d78e6b39b9f6805ea0a8d28", size = 98946649, upload-time = "2025-06-04T17:38:43.031Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/24/efe2f520d75274fc06b695c616415a1e8a1021d87a13c68ff9dce733d088/torch-2.7.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:d632f5417b6980f61404a125b999ca6ebd0b8b4bbdbb5fbbba44374ab619a412", size = 821033192, upload-time = "2025-06-04T17:38:09.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/d9/9c24d230333ff4e9b6807274f6f8d52a864210b52ec794c5def7925f4495/torch-2.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:23660443e13995ee93e3d844786701ea4ca69f337027b05182f5ba053ce43b38", size = 216055668, upload-time = "2025-06-04T17:38:36.253Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/bf/e086ee36ddcef9299f6e708d3b6c8487c1651787bb9ee2939eb2a7f74911/torch-2.7.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0da4f4dba9f65d0d203794e619fe7ca3247a55ffdcbd17ae8fb83c8b2dc9b585", size = 68925988, upload-time = "2025-06-04T17:38:29.273Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/6a/67090dcfe1cf9048448b31555af6efb149f7afa0a310a366adbdada32105/torch-2.7.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:e08d7e6f21a617fe38eeb46dd2213ded43f27c072e9165dc27300c9ef9570934", size = 99028857, upload-time = "2025-06-04T17:37:50.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/1c/48b988870823d1cc381f15ec4e70ed3d65e043f43f919329b0045ae83529/torch-2.7.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:30207f672328a42df4f2174b8f426f354b2baa0b7cca3a0adb3d6ab5daf00dc8", size = 821098066, upload-time = "2025-06-04T17:37:33.939Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/eb/10050d61c9d5140c5dc04a89ed3257ef1a6b93e49dd91b95363d757071e0/torch-2.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:79042feca1c634aaf6603fe6feea8c6b30dfa140a6bbc0b973e2260c7e79a22e", size = 216336310, upload-time = "2025-06-04T17:36:09.862Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/29/beb45cdf5c4fc3ebe282bf5eafc8dfd925ead7299b3c97491900fe5ed844/torch-2.7.1-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:988b0cbc4333618a1056d2ebad9eb10089637b659eb645434d0809d8d937b946", size = 68645708, upload-time = "2025-06-04T17:34:39.852Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "torch-receptive-field"
|
||||
version = "0.1.0"
|
||||
source = { git = "https://github.com/Fangyh09/pytorch-receptive-field.git#0aeb7f80cd1dd8aa1ed8e6a6882f651dd7e6e877" }
|
||||
|
||||
[[package]]
|
||||
name = "torchscan"
|
||||
version = "0.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "torch" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a9/b5/73bc396ae852a3446909421fb8f2943b223f4c83002f9cbca1910d29697e/torchscan-0.1.1.tar.gz", hash = "sha256:672261bc80c39fcb1839c70377a2d580aa233ecb13d34754086120f8e5a0d322", size = 21084, upload-time = "2020-08-03T22:25:38.266Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/30/8f/0f255453c3c44990cb879574ac023f7484acfb225d7f17468cbebc65bf01/torchscan-0.1.1-py3-none-any.whl", hash = "sha256:1084c42a978961aa2098acaefe684e45535749761b1542a44aa91cc18fd52fb9", size = 19005, upload-time = "2020-08-03T22:25:36.966Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triton"
|
||||
version = "3.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/24/5f/950fb373bf9c01ad4eb5a8cd5eaf32cdf9e238c02f9293557a2129b9c4ac/triton-3.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9999e83aba21e1a78c1f36f21bce621b77bcaa530277a50484a7cb4a822f6e43", size = 155669138, upload-time = "2025-05-29T23:39:51.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/1f/dfb531f90a2d367d914adfee771babbd3f1a5b26c3f5fbc458dee21daa78/triton-3.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b89d846b5a4198317fec27a5d3a609ea96b6d557ff44b56c23176546023c4240", size = 155673035, upload-time = "2025-05-29T23:40:02.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/71/bd20ffcb7a64c753dc2463489a61bf69d531f308e390ad06390268c4ea04/triton-3.3.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3198adb9d78b77818a5388bff89fa72ff36f9da0bc689db2f0a651a67ce6a42", size = 155735832, upload-time = "2025-05-29T23:40:10.522Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2025.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "visualtorch"
|
||||
version = "0.2.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aggdraw" },
|
||||
{ name = "numpy" },
|
||||
{ name = "pillow" },
|
||||
{ name = "torch" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2d/09/2c42a3d9c531ee794f235d6eb0a8e49d2b92adf7c6009932349913b2dfb1/visualtorch-0.2.4.tar.gz", hash = "sha256:662e32040533cbbf389cfd12e0a95799f0cf16612bac5eea149e6028bbb36812", size = 17507, upload-time = "2025-06-23T22:19:52.905Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/0f/504fcec35cc8eaf959364482e1dc2b061b279f49fbd0bab0d4df2742ddee/visualtorch-0.2.4-py3-none-any.whl", hash = "sha256:b84e9115204d3a4d1c2d054f85cdcc7ae0e154ece18340622e6ea832736c442c", size = 19965, upload-time = "2025-06-23T22:19:51.734Z" },
|
||||
]
|
||||
@@ -525,7 +525,7 @@ The pre-training results are used in two more key ways. First, the encoder weigh
|
||||
|
||||
In the main training step, DeepSAD's network is trained using SGD backpropagation. The unlabeled training data is used with the goal to minimize an data-encompassing hypersphere. Since one of the pre-conditions of training was the significant prevelance of normal data over anomalies in the training set, normal samples collectively cluster more tightly around the centroid, while the rarer anomalous samples do not contribute as significantly to the optimization, resulting in them staying further from the hypersphere center. The labeled data includes binary class labels signifying their status as either normal or anomalous samples. Labeled anomalies are pushed away from the center by defining their optimization target as maximizing the distance between them and $\mathbf{c}$. Labeled normal samples are treated similar to unlabeled samples with the difference that DeepSAD includes a hyperparameter capable of controling the proportion with which labeled and unlabeled data contribute to the overall optimization. The resulting network has learned to map normal data samples closer to $\mathbf{c}$ in the latent space and anomalies further away.
|
||||
|
||||
\fig{deepsad_procedure}{diagrams/deepsad_procedure}{(WORK IN PROGRESS) Depiction of DeepSAD's training procedure, including data flows and tweakable hyperparameters.}
|
||||
\fig{deepsad_procedure}{diagrams/deepsad_procedure/deepsad_procedure}{(WORK IN PROGRESS) Depiction of DeepSAD's training procedure, including data flows and tweakable hyperparameters.}
|
||||
|
||||
\threadtodo
|
||||
{how to use the trained network?}
|
||||
@@ -988,8 +988,20 @@ We pass instances of this \texttt{Dataset} to PyTorch’s \texttt{DataLoader}, e
|
||||
|
||||
%\todo[inline]{semi-supervised trainingn labels, k_fold, inference dataloader}
|
||||
|
||||
DeepSAD supports both unsupervised and semi-supervised training by optionally incorporating a small number of labeled samples. To control this, our custom PyTorch \texttt{Dataset} accepts two integer parameters, \texttt{num\_labelled\_normal} and \texttt{num\_labelled\_anomalous}, which specify how many samples of each class should retain their labels during training. All other samples are assigned a label of 0 (``unknown'') and treated as unlabeled.
|
||||
|
||||
When using semi-supervised mode, we begin with the manually-defined evaluation labels. We then randomly un-label (set to 0) enough samples of each class until exactly \texttt{num\_labelled\_normal} normals and \texttt{num\_labelled\_anomalous} anomalies remain labeled. This mechanism allows us to systematically compare unsupervised mode, where \texttt{num\_labelled\_normal} = \texttt{num\_labelled\_anomalous} = 0, and Semi-supervised modes with varying label budgets.
|
||||
|
||||
To obtain robust performance estimates on our relatively small dataset, we implement $k$-fold cross-validation. A single integer parameter, \texttt{num\_folds}, controls the number of splits. We use scikit-learn’s \texttt{KFold} (from \texttt{sklearn.model\_selection}) with \texttt{shuffle=True} and a fixed random seed to partition each experiment’s frames into \texttt{num\_folds} disjoint folds. Training then proceeds across $k$ rounds, each time training on $(k-1)/k$ of the data and evaluating on the remaining $1/k$. In our experiments, we set \texttt{num\_folds=5}, yielding an 80/20 train/evaluation split per fold.
|
||||
|
||||
For inference (i.e.\ model validation on held-out experiments), we provide a second \texttt{Dataset} class that loads the full NumPy file for a single experiment (no k-fold splitting), does not assign any labels to the frames nor does it shuffle frames, preserving temporal order. This setup enables seamless, frame-by-frame scoring of complete runs—crucial for analyzing degradation dynamics over an entire traversal.
|
||||
|
||||
\section{Model Configuration \& Evaluation Protocol}
|
||||
|
||||
Since the neural network architecture trained in the deepsad method is not fixed as described in section~\ref{sec:algorithm_details} but rather chosen based on the input data, we also had to choose an autoencoder architecture befitting our preprocessed lidar data projections. Since \citetitle{degradation_quantification_rain}~\cite{degradation_quantification_rain} reported success in training DeepSAD on similar data we firstly adapted their utilized network architecture for our usecase, which is based on the simple and well understood LeNet architecture. Additionally we were interested in evaluating the importance of a well-suited network architecture for DeepSAD's performance and therefore designed a second network architecture henceforth called "efficient architecture" to incorporate a few modern techniques, befitting our usecase.
|
||||
|
||||
|
||||
|
||||
\newsubsubsectionNoTOC{Network architectures (LeNet variant, custom encoder) and how they suit the point‑cloud input}
|
||||
|
||||
\threadtodo
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
texlab
|
||||
zathura
|
||||
wmctrl
|
||||
python312
|
||||
];
|
||||
in
|
||||
{
|
||||
|
||||
3
tools/.gitignore
vendored
3
tools/.gitignore
vendored
@@ -7,4 +7,7 @@ tmp
|
||||
.envrc
|
||||
.vscode
|
||||
test
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.png
|
||||
|
||||
|
||||
174
tools/ae_elbow_eval.py
Normal file
174
tools/ae_elbow_eval.py
Normal file
@@ -0,0 +1,174 @@
|
||||
# loads results from autoencoder training form a pickle file and evaluates results and visualizes them to find traiing elbow
|
||||
|
||||
import pickle
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
results_folder = Path(
|
||||
"/home/fedex/mt/projects/thesis-kowalczyk-jan/Deep-SAD-PyTorch/test/DeepSAD/subter_ae_elbow/"
|
||||
)
|
||||
|
||||
# Find all result files matching the pattern
|
||||
result_files = sorted(
|
||||
results_folder.glob("ae_elbow_results_subter_LeNet_dim_*_kfold.pkl")
|
||||
)
|
||||
|
||||
# Initialize data structures for both classes
|
||||
dimensions = []
|
||||
normal_means = []
|
||||
normal_stds = []
|
||||
anomaly_means = []
|
||||
anomaly_stds = []
|
||||
|
||||
BATCH_SIZE = 256 # Add this constant at the top of the file
|
||||
|
||||
|
||||
def calculate_batch_mean_loss(scores, batch_size=BATCH_SIZE):
|
||||
"""Calculate mean loss over batches similar to the original testing code."""
|
||||
n_samples = len(scores)
|
||||
n_batches = (n_samples + batch_size - 1) // batch_size # ceiling division
|
||||
|
||||
# Split scores into batches
|
||||
batch_losses = []
|
||||
for i in range(0, n_samples, batch_size):
|
||||
batch_scores = scores[i : i + batch_size]
|
||||
batch_losses.append(np.mean(batch_scores))
|
||||
|
||||
return np.sum(batch_losses) / n_batches
|
||||
|
||||
|
||||
def test_loss_calculation(results: Dict, batch_size: int = BATCH_SIZE) -> None:
|
||||
"""Test if our loss calculation matches the original implementation."""
|
||||
test = unittest.TestCase()
|
||||
folds = results["ae_results"]
|
||||
dim = results["dimension"]
|
||||
|
||||
for fold_key in folds:
|
||||
fold_data = folds[fold_key]["test"]
|
||||
scores = np.array(fold_data["scores"])
|
||||
original_loss = fold_data["loss"]
|
||||
calculated_loss = calculate_batch_mean_loss(scores)
|
||||
|
||||
try:
|
||||
test.assertAlmostEqual(
|
||||
original_loss,
|
||||
calculated_loss,
|
||||
places=5,
|
||||
msg=f"Loss mismatch for dim={dim}, {fold_key}",
|
||||
)
|
||||
except AssertionError as e:
|
||||
print(f"Warning: {str(e)}")
|
||||
print(f"Original: {original_loss:.6f}, Calculated: {calculated_loss:.6f}")
|
||||
raise
|
||||
|
||||
|
||||
# Load and verify data
|
||||
print("Verifying loss calculation implementation...")
|
||||
for result_file in result_files:
|
||||
with open(result_file, "rb") as f:
|
||||
results = pickle.load(f)
|
||||
test_loss_calculation(results)
|
||||
print("Loss calculation verified successfully!")
|
||||
|
||||
# Continue with actual data processing
|
||||
for result_file in result_files:
|
||||
with open(result_file, "rb") as f:
|
||||
results = pickle.load(f)
|
||||
dim = int(results["dimension"])
|
||||
folds = results["ae_results"]
|
||||
|
||||
normal_fold_losses = []
|
||||
anomaly_fold_losses = []
|
||||
|
||||
for fold_key in folds:
|
||||
fold_data = folds[fold_key]["test"]
|
||||
scores = np.array(fold_data["scores"])
|
||||
labels = np.array(fold_data["labels_exp_based"])
|
||||
|
||||
# Calculate mean loss for normal and anomaly samples
|
||||
normal_scores = scores[labels == 1]
|
||||
anomaly_scores = scores[labels == -1]
|
||||
|
||||
# Calculate losses using batch means
|
||||
normal_fold_losses.append(calculate_batch_mean_loss(normal_scores))
|
||||
anomaly_fold_losses.append(calculate_batch_mean_loss(anomaly_scores))
|
||||
|
||||
dimensions.append(dim)
|
||||
normal_means.append(np.mean(normal_fold_losses))
|
||||
normal_stds.append(np.std(normal_fold_losses))
|
||||
anomaly_means.append(np.mean(anomaly_fold_losses))
|
||||
anomaly_stds.append(np.std(anomaly_fold_losses))
|
||||
|
||||
# Sort by dimension
|
||||
dims, n_means, n_stds, a_means, a_stds = zip(
|
||||
*sorted(zip(dimensions, normal_means, normal_stds, anomaly_means, anomaly_stds))
|
||||
)
|
||||
|
||||
# Calculate overall means and stds
|
||||
means = [(n + a) / 2 for n, a in zip(n_means, a_means)]
|
||||
stds = [(ns + as_) / 2 for ns, as_ in zip(n_stds, a_stds)]
|
||||
|
||||
|
||||
def plot_loss_curve(dims, means, stds, title, color, output_path):
|
||||
"""Create and save a single loss curve plot.
|
||||
|
||||
Args:
|
||||
dims: List of latent dimensions
|
||||
means: List of mean losses
|
||||
stds: List of standard deviations
|
||||
title: Plot title
|
||||
color: Color for plot and fill
|
||||
output_path: Where to save the plot
|
||||
"""
|
||||
plt.figure(figsize=(8, 5))
|
||||
plt.plot(dims, means, marker="o", color=color, label="Mean Test Loss")
|
||||
plt.fill_between(
|
||||
dims,
|
||||
np.array(means) - np.array(stds),
|
||||
np.array(means) + np.array(stds),
|
||||
color=color,
|
||||
alpha=0.2,
|
||||
label="Std Dev",
|
||||
)
|
||||
plt.xlabel("Latent Dimension")
|
||||
plt.ylabel("Test Loss")
|
||||
plt.title(title)
|
||||
plt.legend()
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.xticks(dims) # Set x-ticks exactly at all data points
|
||||
plt.tight_layout()
|
||||
plt.savefig(output_path, dpi=150, bbox_inches="tight")
|
||||
plt.close()
|
||||
|
||||
|
||||
# Create the three plots
|
||||
plot_loss_curve(
|
||||
dims,
|
||||
means,
|
||||
stds,
|
||||
"Overall Test Loss vs. Latent Dimension",
|
||||
"blue",
|
||||
results_folder / "ae_elbow_test_loss_overall.png",
|
||||
)
|
||||
|
||||
plot_loss_curve(
|
||||
dims,
|
||||
n_means,
|
||||
n_stds,
|
||||
"Normal Class Test Loss vs. Latent Dimension",
|
||||
"green",
|
||||
results_folder / "ae_elbow_test_loss_normal.png",
|
||||
)
|
||||
|
||||
plot_loss_curve(
|
||||
dims,
|
||||
a_means,
|
||||
a_stds,
|
||||
"Anomaly Class Test Loss vs. Latent Dimension",
|
||||
"red",
|
||||
results_folder / "ae_elbow_test_loss_anomaly.png",
|
||||
)
|
||||
23
tools/calculate_conv_dimensions.py
Normal file
23
tools/calculate_conv_dimensions.py
Normal file
@@ -0,0 +1,23 @@
|
||||
def calculate_conv_dimensions(W_in, H_in, K, S, P):
|
||||
"""
|
||||
Calculate the output dimensions of a convolutional layer.
|
||||
|
||||
Parameters:
|
||||
W_in (int): Width of the input image
|
||||
H_in (int): Height of the input image
|
||||
K (int): Size of the filter (assumed to be square)
|
||||
S (int): Stride
|
||||
P (int): Padding
|
||||
|
||||
Returns:
|
||||
(int, int): Width and height of the output activation map
|
||||
"""
|
||||
W_out = (W_in - K + (2 * P)) / S + 1
|
||||
H_out = (H_in - K + (2 * P)) / S + 1
|
||||
|
||||
return W_out, H_out
|
||||
|
||||
|
||||
print(f"w, h = {calculate_conv_dimensions(W_in=2048, H_in=32, K=11, S=4, P=2)=}")
|
||||
# w, h = calculate_conv_dimensions(W_in=2048, H_in=32, K=11, S=4, P=2)
|
||||
# print(f"{calculate_conv_dimensions(W_in=w, H_in=h, K=11, S=4, P=2)=}")
|
||||
102
tools/calculate_rf_sizes.py
Normal file
102
tools/calculate_rf_sizes.py
Normal file
@@ -0,0 +1,102 @@
|
||||
def calculate_receptive_field_size(layers):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
layers : list of dict
|
||||
Each dict must contain
|
||||
─ 'kernel_size' : (k_h, k_w)
|
||||
─ 'stride' : (s_h, s_w)
|
||||
─ 'dilation' : (d_h, d_w) # optional; defaults to (1, 1)
|
||||
|
||||
Returns
|
||||
-------
|
||||
(rf_h, rf_w) : tuple of ints
|
||||
Receptive-field size in pixels for height and width.
|
||||
"""
|
||||
rf_h = rf_w = 1 # start with a 1×1 pixel
|
||||
jump_h = jump_w = 1 # effective stride so far
|
||||
|
||||
for layer in layers:
|
||||
k_h, k_w = layer["kernel_size"]
|
||||
s_h, s_w = layer["stride"]
|
||||
d_h, d_w = layer.get("dilation", (1, 1)) # default = 1
|
||||
|
||||
# Dumoulin & Visin recurrence, now with dilation
|
||||
rf_h += (k_h - 1) * d_h * jump_h
|
||||
rf_w += (k_w - 1) * d_w * jump_w
|
||||
|
||||
jump_h *= s_h
|
||||
jump_w *= s_w
|
||||
|
||||
return rf_h, rf_w
|
||||
|
||||
|
||||
def calculate_angular_receptive_field(
|
||||
rf_height: int,
|
||||
rf_width: int,
|
||||
vertical_res: int,
|
||||
horizontal_res: int,
|
||||
vertical_fov: float,
|
||||
horizontal_fov: float,
|
||||
) -> tuple[float, float]:
|
||||
"""Calculate the angular size of a receptive field in degrees.
|
||||
|
||||
Args:
|
||||
rf_height: Receptive field height in pixels
|
||||
rf_width: Receptive field width in pixels
|
||||
vertical_res: Vertical resolution of input in pixels
|
||||
horizontal_res: Horizontal resolution of input in pixels
|
||||
vertical_fov: Vertical field of view in degrees
|
||||
horizontal_fov: Horizontal field of view in degrees
|
||||
|
||||
Returns:
|
||||
tuple[float, float]: Angular size (height, width) in degrees
|
||||
"""
|
||||
# Calculate degrees per pixel for each axis
|
||||
vertical_deg_per_pixel = vertical_fov / vertical_res
|
||||
horizontal_deg_per_pixel = horizontal_fov / horizontal_res
|
||||
|
||||
# Calculate angular size of receptive field
|
||||
rf_vertical_deg = rf_height * vertical_deg_per_pixel
|
||||
rf_horizontal_deg = rf_width * horizontal_deg_per_pixel
|
||||
|
||||
return rf_vertical_deg, rf_horizontal_deg
|
||||
|
||||
|
||||
horizontal_resolution = 2048
|
||||
horizontal_fov = 360.0
|
||||
vertical_resolution = 32
|
||||
vertical_fov = 31.76
|
||||
|
||||
lenet_network_config = [
|
||||
{"name": "Conv1", "kernel_size": (5, 5), "stride": (1, 1), "dilation": (1, 1)},
|
||||
{"name": "MaxPool1", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
|
||||
{"name": "Conv2", "kernel_size": (5, 5), "stride": (1, 1), "dilation": (1, 1)},
|
||||
{"name": "MaxPool2", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
|
||||
]
|
||||
|
||||
# Calculate and print results for LeNet
|
||||
rf_h, rf_w = calculate_receptive_field_size(lenet_network_config)
|
||||
rf_vert_deg, rf_horiz_deg = calculate_angular_receptive_field(
|
||||
rf_h, rf_w, vertical_resolution, horizontal_resolution, vertical_fov, horizontal_fov
|
||||
)
|
||||
print(f"SubTer LeNet RF size: {rf_h} × {rf_w} pixels")
|
||||
print(f"SubTer LeNet RF angular size: {rf_vert_deg:.2f}° × {rf_horiz_deg:.2f}°")
|
||||
|
||||
|
||||
asym_network_config = [
|
||||
{"name": "Conv1", "kernel_size": (3, 17), "stride": (1, 1), "dilation": (1, 1)},
|
||||
{"name": "MaxPool1", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
|
||||
{"name": "Conv2", "kernel_size": (3, 17), "stride": (1, 1), "dilation": (1, 1)},
|
||||
{"name": "MaxPool2", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
|
||||
]
|
||||
|
||||
# Calculate and print results for Asymmetric network
|
||||
rf_h, rf_w = calculate_receptive_field_size(asym_network_config)
|
||||
rf_vert_deg, rf_horiz_deg = calculate_angular_receptive_field(
|
||||
rf_h, rf_w, vertical_resolution, horizontal_resolution, vertical_fov, horizontal_fov
|
||||
)
|
||||
print(f"SubTer LeNet (Asymmetric kernels) RF size: {rf_h} × {rf_w} pixels")
|
||||
print(
|
||||
f"SubTer LeNet (Asymmetric kernels) RF angular size: {rf_vert_deg:.2f}° × {rf_horiz_deg:.2f}°"
|
||||
)
|
||||
205
tools/compare_projections.py
Normal file
205
tools/compare_projections.py
Normal file
@@ -0,0 +1,205 @@
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
import numpy as np
|
||||
|
||||
# Configuration
|
||||
old_projections_path = Path("/home/fedex/mt/data/subter")
|
||||
new_projections_path = Path("/home/fedex/mt/data/subter/new_projection")
|
||||
|
||||
|
||||
def get_file_info(file_path: Path) -> Optional[dict]:
|
||||
"""Get detailed information about a .npy file."""
|
||||
if not file_path.exists():
|
||||
return None
|
||||
try:
|
||||
with file_path.open("rb") as f:
|
||||
return {
|
||||
"size": file_path.stat().st_size,
|
||||
"format": np.lib.format.read_magic(f),
|
||||
"header": np.lib.format.read_array_header_1_0(f),
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error reading file {file_path}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_array_info(arr: np.ndarray) -> dict:
|
||||
"""Get detailed information about a numpy array."""
|
||||
return {
|
||||
"dtype": str(arr.dtype),
|
||||
"itemsize": arr.itemsize,
|
||||
"nbytes": arr.nbytes,
|
||||
"byteorder": arr.dtype.byteorder,
|
||||
"shape": arr.shape,
|
||||
"nan_count": np.sum(np.isnan(arr)),
|
||||
"inf_count": np.sum(np.isinf(arr)),
|
||||
}
|
||||
|
||||
|
||||
def compare_arrays(old_arr: np.ndarray, new_arr: np.ndarray) -> dict:
|
||||
"""Compare two numpy arrays and return detailed differences."""
|
||||
# Get basic array information
|
||||
old_info = get_array_info(old_arr)
|
||||
new_info = get_array_info(new_arr)
|
||||
|
||||
differences = {
|
||||
"old_info": old_info,
|
||||
"new_info": new_info,
|
||||
"shape_mismatch": old_arr.shape != new_arr.shape,
|
||||
}
|
||||
|
||||
if differences["shape_mismatch"]:
|
||||
return differences
|
||||
|
||||
# Compare values
|
||||
both_nan = np.isnan(old_arr) & np.isnan(new_arr)
|
||||
unequal = (old_arr != new_arr) & ~both_nan
|
||||
mismatch_indices = np.where(unequal)
|
||||
|
||||
differences.update(
|
||||
{
|
||||
"num_mismatches": mismatch_indices[0].size,
|
||||
"mismatch_indices": mismatch_indices
|
||||
if mismatch_indices[0].size > 0
|
||||
else None,
|
||||
"mean_difference": np.mean(np.abs(old_arr - new_arr)),
|
||||
"std_difference": np.std(old_arr - new_arr),
|
||||
"new_zeros": np.sum(new_arr == 0),
|
||||
}
|
||||
)
|
||||
|
||||
# If there are mismatches, store some example values
|
||||
if differences["num_mismatches"] > 0:
|
||||
old_values = old_arr[mismatch_indices][:10]
|
||||
new_values = new_arr[mismatch_indices][:10]
|
||||
differences.update(
|
||||
{
|
||||
"example_old_values": old_values,
|
||||
"example_new_values": new_values,
|
||||
"all_new_mismatches_zero": np.all(new_arr[mismatch_indices] == 0),
|
||||
}
|
||||
)
|
||||
|
||||
return differences
|
||||
|
||||
|
||||
def print_detailed_comparison(name: str, diff: dict):
|
||||
"""Print detailed comparison results for a single file."""
|
||||
print(f"\nDetailed comparison for: {name}")
|
||||
print("=" * 80)
|
||||
|
||||
# Storage information
|
||||
old_info = diff["old_info"]
|
||||
new_info = diff["new_info"]
|
||||
print(f"Storage Information:")
|
||||
print(f" Dtype: {old_info['dtype']} → {new_info['dtype']}")
|
||||
print(f" Item size: {old_info['itemsize']} → {new_info['itemsize']} bytes")
|
||||
print(f" Total bytes: {old_info['nbytes']} → {new_info['nbytes']}")
|
||||
print(f" Byte ratio: {new_info['nbytes'] / old_info['nbytes']:.2f}")
|
||||
|
||||
# Shape information
|
||||
if diff["shape_mismatch"]:
|
||||
print(f"Shape mismatch: {old_info['shape']} → {new_info['shape']}")
|
||||
return
|
||||
|
||||
# Value differences
|
||||
if diff["num_mismatches"] > 0:
|
||||
print(f"\nValue Differences:")
|
||||
print(f" Number of mismatches: {diff['num_mismatches']}")
|
||||
print(f" Mean difference: {diff['mean_difference']:.2e}")
|
||||
print(f" Std difference: {diff['std_difference']:.2e}")
|
||||
print(f" Example mismatches (old → new):")
|
||||
for old_val, new_val in zip(
|
||||
diff["example_old_values"], diff["example_new_values"]
|
||||
):
|
||||
print(f" {old_val:.6e} → {new_val:.6e}")
|
||||
if diff["all_new_mismatches_zero"]:
|
||||
print(" Note: All mismatched values in new array are zero")
|
||||
else:
|
||||
print("\nNo value mismatches found.")
|
||||
|
||||
|
||||
def summarize_differences(all_differences: Dict[str, dict]) -> str:
|
||||
"""Create a summary of all differences."""
|
||||
summary = []
|
||||
summary.append("\nSUMMARY OF ALL DIFFERENCES")
|
||||
summary.append("=" * 80)
|
||||
|
||||
total_files = len(all_differences)
|
||||
files_with_mismatches = sum(
|
||||
1 for d in all_differences.values() if d["num_mismatches"] > 0
|
||||
)
|
||||
files_with_shape_mismatch = sum(
|
||||
1 for d in all_differences.values() if d["shape_mismatch"]
|
||||
)
|
||||
|
||||
summary.append(f"Total files compared: {total_files}")
|
||||
summary.append(f"Files with shape mismatches: {files_with_shape_mismatch}")
|
||||
summary.append(f"Files with value mismatches: {files_with_mismatches}")
|
||||
|
||||
if files_with_mismatches > 0:
|
||||
summary.append("\nFiles with differences:")
|
||||
for name, diff in all_differences.items():
|
||||
if diff["num_mismatches"] > 0:
|
||||
summary.append(f" {name}:")
|
||||
summary.append(f" Mismatches: {diff['num_mismatches']}")
|
||||
summary.append(f" Mean difference: {diff['mean_difference']:.2e}")
|
||||
if diff.get("all_new_mismatches_zero", False):
|
||||
summary.append(" All mismatches are zeros in new file")
|
||||
|
||||
return "\n".join(summary)
|
||||
|
||||
|
||||
def main():
|
||||
# Get list of all .npy files
|
||||
old_files = list(old_projections_path.glob("*.npy"))
|
||||
new_files = list(new_projections_path.glob("*.npy"))
|
||||
|
||||
# Check for missing files
|
||||
old_names = {f.stem for f in old_files}
|
||||
new_names = {f.stem for f in new_files}
|
||||
if missing := (old_names - new_names):
|
||||
print(f"Files missing in new directory: {missing}")
|
||||
if missing := (new_names - old_names):
|
||||
print(f"Files missing in old directory: {missing}")
|
||||
|
||||
# Compare common files
|
||||
all_differences = {}
|
||||
for old_file in old_files:
|
||||
if old_file.stem not in new_names:
|
||||
continue
|
||||
|
||||
print(f"\nComparing {old_file.stem}...")
|
||||
new_file = new_projections_path / f"{old_file.stem}.npy"
|
||||
|
||||
# Check file info before loading
|
||||
old_info = get_file_info(old_file)
|
||||
new_info = get_file_info(new_file)
|
||||
|
||||
if not old_info or not new_info:
|
||||
print(f"Skipping {old_file.stem} due to file reading errors")
|
||||
continue
|
||||
|
||||
try:
|
||||
# Load arrays
|
||||
old_arr = np.load(old_file)
|
||||
new_arr = np.load(new_file)
|
||||
|
||||
# Compare and print detailed results
|
||||
differences = compare_arrays(old_arr, new_arr)
|
||||
print_detailed_comparison(old_file.stem, differences)
|
||||
all_differences[old_file.stem] = differences
|
||||
except Exception as e:
|
||||
print(f"Error processing {old_file.stem}: {e}")
|
||||
continue
|
||||
|
||||
# Print summary
|
||||
if all_differences:
|
||||
print(summarize_differences(all_differences))
|
||||
else:
|
||||
print("\nNo valid comparisons were made.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
600
tools/elbow_structure.txt
Normal file
600
tools/elbow_structure.txt
Normal file
@@ -0,0 +1,600 @@
|
||||
|
||||
=== Results for ae_elbow_results_subter_LeNet_dim_32_kfold.pkl ===
|
||||
dimension:
|
||||
32
|
||||
ae_results:
|
||||
fold_0:
|
||||
train:
|
||||
time:
|
||||
47.35341715812683
|
||||
indices:
|
||||
[ 6547 6096 17322 ... 14590 6764 6219]
|
||||
labels_exp_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 1 1 ... 1 1 1]
|
||||
file_ids:
|
||||
[8 5 0 ... 1 9 1]
|
||||
frame_ids:
|
||||
[1260 569 2387 ... 3064 205 1096]
|
||||
scores:
|
||||
[0.06785126 0.13130851 0.10918648 ... 0.04708466 0.03133186 0.05559417]
|
||||
loss:
|
||||
0.07233340218663216
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
test:
|
||||
time:
|
||||
3.2727890014648438
|
||||
indices:
|
||||
[ 0 1 2 ... 5883 5884 5885]
|
||||
labels_exp_based:
|
||||
[ 1 1 1 ... -1 1 -1]
|
||||
labels_manual_based:
|
||||
[ 1 1 1 ... -1 1 -1]
|
||||
semi_targets:
|
||||
[ 1 1 1 ... -1 1 -1]
|
||||
file_ids:
|
||||
[ 0 1 3 ... 11 0 12]
|
||||
frame_ids:
|
||||
[3373 2260 81 ... 405 1342 335]
|
||||
scores:
|
||||
[0.28987885 0.06485476 0.03065375 ... 0.26596928 0.03807792 0.46061364]
|
||||
loss:
|
||||
0.06829473586833995
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
fold_1:
|
||||
train:
|
||||
time:
|
||||
46.584895849227905
|
||||
indices:
|
||||
[14909 2898 15177 ... 3185 2297 2518]
|
||||
labels_exp_based:
|
||||
[ 1 1 1 ... 1 -1 1]
|
||||
labels_manual_based:
|
||||
[ 1 1 1 ... 1 -1 1]
|
||||
semi_targets:
|
||||
[ 1 1 1 ... 1 -1 1]
|
||||
file_ids:
|
||||
[ 5 6 1 ... 7 13 4]
|
||||
frame_ids:
|
||||
[ 936 606 3193 ... 989 86 844]
|
||||
scores:
|
||||
[0.10743871 0.17937626 0.3385203 ... 0.02518196 0.3909377 0.02823789]
|
||||
loss:
|
||||
0.06587159360448519
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
test:
|
||||
time:
|
||||
3.254101037979126
|
||||
indices:
|
||||
[ 5886 5887 5888 ... 11769 11770 11771]
|
||||
labels_exp_based:
|
||||
[ 1 1 -1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 1 0 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 1 0 ... 1 1 1]
|
||||
file_ids:
|
||||
[ 0 1 12 ... 0 1 7]
|
||||
frame_ids:
|
||||
[2943 4 179 ... 348 663 423]
|
||||
scores:
|
||||
[0.02836892 0.03712069 0.13963991 ... 0.07210366 0.02482101 0.07186633]
|
||||
loss:
|
||||
0.059809695119443146
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
fold_2:
|
||||
train:
|
||||
time:
|
||||
47.0039427280426
|
||||
indices:
|
||||
[ 4709 10566 1669 ... 4887 6760 1348]
|
||||
labels_exp_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 1 1 ... 1 1 1]
|
||||
file_ids:
|
||||
[0 6 1 ... 8 5 0]
|
||||
frame_ids:
|
||||
[1701 990 2584 ... 1036 610 449]
|
||||
scores:
|
||||
[0.07715754 0.07710524 0.11718763 ... 0.03398419 0.07341428 0.03260035]
|
||||
loss:
|
||||
0.06793700895375676
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
test:
|
||||
time:
|
||||
3.3094074726104736
|
||||
indices:
|
||||
[11772 11773 11774 ... 17655 17656 17657]
|
||||
labels_exp_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 1 1 ... 1 1 1]
|
||||
file_ids:
|
||||
[7 8 0 ... 4 5 0]
|
||||
frame_ids:
|
||||
[ 98 1000 873 ... 674 541 2732]
|
||||
scores:
|
||||
[0.033662 0.03786198 0.04839528 ... 0.07525856 0.07365932 0.0603102 ]
|
||||
loss:
|
||||
0.06470830592772235
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
k_fold:
|
||||
True
|
||||
k_fold_num:
|
||||
3
|
||||
|
||||
=== Results for ae_elbow_results_subter_LeNet_dim_64_kfold.pkl ===
|
||||
dimension:
|
||||
64
|
||||
ae_results:
|
||||
fold_0:
|
||||
train:
|
||||
time:
|
||||
47.33047151565552
|
||||
indices:
|
||||
[11876 12634 14187 ... 13309 8275 16184]
|
||||
labels_exp_based:
|
||||
[ 1 -1 1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 0 1 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 0 1 ... 1 1 1]
|
||||
file_ids:
|
||||
[ 4 12 8 ... 0 7 4]
|
||||
frame_ids:
|
||||
[ 545 63 1159 ... 441 992 700]
|
||||
scores:
|
||||
[0.13897061 0.08483056 0.07720029 ... 0.02398726 0.02211376 0.05582099]
|
||||
loss:
|
||||
0.05624731986059083
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
test:
|
||||
time:
|
||||
3.393460512161255
|
||||
indices:
|
||||
[ 0 1 2 ... 5883 5884 5885]
|
||||
labels_exp_based:
|
||||
[ 1 1 1 ... -1 1 -1]
|
||||
labels_manual_based:
|
||||
[ 1 1 1 ... -1 1 -1]
|
||||
semi_targets:
|
||||
[ 1 1 1 ... -1 1 -1]
|
||||
file_ids:
|
||||
[ 0 1 3 ... 11 0 12]
|
||||
frame_ids:
|
||||
[3373 2260 81 ... 405 1342 335]
|
||||
scores:
|
||||
[0.19174853 0.04987323 0.0225831 ... 0.19634478 0.03153864 0.39142317]
|
||||
loss:
|
||||
0.05257830946989681
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
fold_1:
|
||||
train:
|
||||
time:
|
||||
47.514824867248535
|
||||
indices:
|
||||
[13393 1405 12413 ... 14812 397 14801]
|
||||
labels_exp_based:
|
||||
[ 1 -1 1 ... -1 1 1]
|
||||
labels_manual_based:
|
||||
[ 1 0 1 ... -1 1 1]
|
||||
semi_targets:
|
||||
[ 1 0 1 ... -1 1 1]
|
||||
file_ids:
|
||||
[ 3 10 8 ... 10 9 7]
|
||||
frame_ids:
|
||||
[1059 161 236 ... 368 480 145]
|
||||
scores:
|
||||
[0.08272791 0.17799513 0.07856707 ... 0.16969317 0.09914576 0.04465985]
|
||||
loss:
|
||||
0.08280573851532406
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
test:
|
||||
time:
|
||||
3.303018808364868
|
||||
indices:
|
||||
[ 5886 5887 5888 ... 11769 11770 11771]
|
||||
labels_exp_based:
|
||||
[ 1 1 -1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 1 0 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 1 0 ... 1 1 1]
|
||||
file_ids:
|
||||
[ 0 1 12 ... 0 1 7]
|
||||
frame_ids:
|
||||
[2943 4 179 ... 348 663 423]
|
||||
scores:
|
||||
[0.03737867 0.05766786 0.15279752 ... 0.07271019 0.04369381 0.10203677]
|
||||
loss:
|
||||
0.07809325761121252
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
fold_2:
|
||||
train:
|
||||
time:
|
||||
49.39735269546509
|
||||
indices:
|
||||
[6159 8197 617 ... 5118 8505 8730]
|
||||
labels_exp_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 1 1 ... 1 1 1]
|
||||
file_ids:
|
||||
[1 1 0 ... 6 5 0]
|
||||
frame_ids:
|
||||
[ 113 169 48 ... 741 231 2666]
|
||||
scores:
|
||||
[0.0654774 0.06249695 0.06091163 ... 0.01456711 0.0128163 0.0202495 ]
|
||||
loss:
|
||||
0.03804728595746888
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
test:
|
||||
time:
|
||||
3.464538812637329
|
||||
indices:
|
||||
[11772 11773 11774 ... 17655 17656 17657]
|
||||
labels_exp_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
labels_manual_based:
|
||||
[1 1 1 ... 1 1 1]
|
||||
semi_targets:
|
||||
[1 1 1 ... 1 1 1]
|
||||
file_ids:
|
||||
[7 8 0 ... 4 5 0]
|
||||
frame_ids:
|
||||
[ 98 1000 873 ... 674 541 2732]
|
||||
scores:
|
||||
[0.01374984 0.01219883 0.01543648 ... 0.01943305 0.01877283 0.02498569]
|
||||
loss:
|
||||
0.03719014423372953
|
||||
file_names:
|
||||
0:
|
||||
1_loop_closure_illuminated_2023-01-23.npy
|
||||
1:
|
||||
1_loop_closure_illuminated_two_LiDARs_2023-01-23.npy
|
||||
2:
|
||||
2_human_static_illuminated_2023-01-23-001.npy
|
||||
3:
|
||||
2_human_static_no_illumination_2023-01-23-001.npy
|
||||
4:
|
||||
2_human_walking_illuminated_2023-01-23-001.npy
|
||||
5:
|
||||
2_human_walking_no_illumination_2023-01-23-001.npy
|
||||
6:
|
||||
2_static_artifacts_illuminated_2023-01-23-001.npy
|
||||
7:
|
||||
2_static_artifacts_no_illumination_2023-01-23-001.npy
|
||||
8:
|
||||
2_static_no_artifacts_illuminated_2023-01-23-001.npy
|
||||
9:
|
||||
2_static_no_artifacts_no_illumination_2023-01-23-001.npy
|
||||
10:
|
||||
3_smoke_artifacts_human_static_2023-01-23-001.npy
|
||||
11:
|
||||
3_smoke_human_walking_2023-01-23.npy
|
||||
12:
|
||||
3_smoke_no_artifacts_2023-01-23.npy
|
||||
13:
|
||||
3_smoke_robot_stationary_static_excess_smoke_2023-01-23.npy
|
||||
k_fold:
|
||||
True
|
||||
k_fold_num:
|
||||
3
|
||||
@@ -1,13 +1,18 @@
|
||||
import json
|
||||
import pickle
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from rich.progress import track
|
||||
from scipy.stats import sem, t
|
||||
from sklearn.metrics import auc
|
||||
|
||||
models = ["deepsad", "isoforest", "ocsvm"]
|
||||
evaluation_types = ["exp_based", "manual_based"]
|
||||
parent_results_path = Path("/home/fedex/mt/results/done")
|
||||
base_output_path = Path("/home/fedex/mt/results/tmp_plots")
|
||||
|
||||
|
||||
# Confidence interval function
|
||||
def confidence_interval(data, confidence=0.95):
|
||||
n = len(data)
|
||||
mean = np.mean(data)
|
||||
@@ -16,67 +21,178 @@ def confidence_interval(data, confidence=0.95):
|
||||
return mean, h
|
||||
|
||||
|
||||
# Load ROC and AUC values from pickle files
|
||||
roc_data = []
|
||||
auc_scores = []
|
||||
isoforest_roc_data = []
|
||||
isoforest_auc_scores = []
|
||||
def load_results_data(folder):
|
||||
experiment_data = {}
|
||||
|
||||
results_path = Path(
|
||||
"/home/fedex/mt/projects/thesis-kowalczyk-jan/Deep-SAD-PyTorch/log/DeepSAD/subter_kfold_0_0"
|
||||
)
|
||||
json_config_path = folder / "config.json"
|
||||
with json_config_path.open("r") as f:
|
||||
config = json.load(f)
|
||||
try:
|
||||
net = config["net_name"]
|
||||
num_known_normal, num_known_anomalous = (
|
||||
config["num_known_normal"],
|
||||
config["num_known_outlier"],
|
||||
)
|
||||
semi_known_nums = (num_known_normal, num_known_anomalous)
|
||||
latent_dim = config["latent_space_dim"]
|
||||
|
||||
for i in range(5):
|
||||
with (results_path / f"results_{i}.pkl").open("rb") as f:
|
||||
data = pickle.load(f)
|
||||
roc_data.append(data["test_roc"])
|
||||
auc_scores.append(data["test_auc"])
|
||||
with (results_path / f"results.isoforest_{i}.pkl").open("rb") as f:
|
||||
data = pickle.load(f)
|
||||
isoforest_roc_data.append(data["test_roc"])
|
||||
isoforest_auc_scores.append(data["test_auc"])
|
||||
exp_title = f"{net} - {num_known_normal} normal, {num_known_anomalous} anomalous, latent dim {latent_dim}"
|
||||
|
||||
# Calculate mean and confidence interval for AUC scores
|
||||
mean_auc, auc_ci = confidence_interval(auc_scores)
|
||||
if not config["k_fold"]:
|
||||
raise ValueError(f"{folder.name} was not trained as k-fold. Exiting...")
|
||||
|
||||
# Combine ROC curves
|
||||
mean_fpr = np.linspace(0, 1, 100)
|
||||
tprs = []
|
||||
k_fold_num = config["k_fold_num"]
|
||||
except KeyError as e:
|
||||
print(f"Missing key in config.json for experiment folder {folder.name}: {e}")
|
||||
raise
|
||||
|
||||
for fpr, tpr, _ in roc_data:
|
||||
interp_tpr = np.interp(mean_fpr, fpr, tpr)
|
||||
interp_tpr[0] = 0.0
|
||||
tprs.append(interp_tpr)
|
||||
experiment_data["exp_title"] = exp_title
|
||||
experiment_data["k_fold_num"] = k_fold_num
|
||||
experiment_data["semi_known_nums"] = semi_known_nums
|
||||
experiment_data["folder"] = folder
|
||||
experiment_data["net"] = net
|
||||
experiment_data["latent_dim"] = latent_dim
|
||||
|
||||
mean_tpr = np.mean(tprs, axis=0)
|
||||
mean_tpr[-1] = 1.0
|
||||
std_tpr = np.std(tprs, axis=0)
|
||||
roc_data = {}
|
||||
roc_auc_data = {}
|
||||
prc_data = {}
|
||||
|
||||
# Plot ROC curves with confidence margins
|
||||
plt.figure()
|
||||
plt.plot(
|
||||
mean_fpr,
|
||||
mean_tpr,
|
||||
color="b",
|
||||
label=f"Mean ROC (AUC = {mean_auc:.2f} ± {auc_ci:.2f})",
|
||||
)
|
||||
plt.fill_between(
|
||||
mean_fpr,
|
||||
mean_tpr - std_tpr,
|
||||
mean_tpr + std_tpr,
|
||||
color="b",
|
||||
alpha=0.2,
|
||||
label="± 1 std. dev.",
|
||||
)
|
||||
for model in models:
|
||||
# You can adjust the number of folds if needed
|
||||
for fold_idx in range(k_fold_num):
|
||||
results_file = folder / f"results_{model}_{fold_idx}.pkl"
|
||||
if not results_file.exists():
|
||||
print(
|
||||
f"Expected results file {results_file.name} does not exist. Skipping..."
|
||||
)
|
||||
with results_file.open("rb") as f:
|
||||
data = pickle.load(f)
|
||||
try:
|
||||
if model == "deepsad":
|
||||
test_results = data["test"]
|
||||
for evaluation_type in evaluation_types:
|
||||
eval_type_results = test_results[evaluation_type]
|
||||
roc_data.setdefault(model, {}).setdefault(
|
||||
evaluation_type, {}
|
||||
)[fold_idx] = eval_type_results["roc"]
|
||||
roc_auc_data.setdefault(model, {}).setdefault(
|
||||
evaluation_type, {}
|
||||
)[fold_idx] = eval_type_results["auc"]
|
||||
prc_data.setdefault(model, {}).setdefault(
|
||||
evaluation_type, {}
|
||||
)[fold_idx] = eval_type_results["prc"]
|
||||
elif model in ["isoforest", "ocsvm"]:
|
||||
for evaluation_type in evaluation_types:
|
||||
roc_data.setdefault(model, {}).setdefault(
|
||||
evaluation_type, {}
|
||||
)[fold_idx] = data[f"test_roc_{evaluation_type}"]
|
||||
roc_auc_data.setdefault(model, {}).setdefault(
|
||||
evaluation_type, {}
|
||||
)[fold_idx] = data[f"test_auc_{evaluation_type}"]
|
||||
prc_data.setdefault(model, {}).setdefault(
|
||||
evaluation_type, {}
|
||||
)[fold_idx] = data[f"test_prc_{evaluation_type}"]
|
||||
|
||||
# Plot each fold's ROC curve (optional)
|
||||
for i, (fpr, tpr, _) in enumerate(roc_data):
|
||||
plt.plot(fpr, tpr, lw=1, alpha=0.3, label=f"Fold {i + 1} ROC")
|
||||
except KeyError as e:
|
||||
print(f"Missing key in results file {results_file.name}: {e}")
|
||||
raise
|
||||
|
||||
# Labels and legend
|
||||
plt.plot([0, 1], [0, 1], "k--", label="Chance")
|
||||
plt.xlabel("False Positive Rate")
|
||||
plt.ylabel("True Positive Rate")
|
||||
plt.title("ROC Curve with 5-Fold Cross-Validation")
|
||||
plt.legend(loc="lower right")
|
||||
plt.savefig("roc_curve_0_0.png")
|
||||
experiment_data["roc_data"] = roc_data
|
||||
experiment_data["roc_auc_data"] = roc_auc_data
|
||||
experiment_data["prc_data"] = prc_data
|
||||
return experiment_data
|
||||
|
||||
|
||||
def plot_roc_curve(experiment_data, output_path):
|
||||
try:
|
||||
k_fold_num = experiment_data["k_fold_num"]
|
||||
roc_data = experiment_data["roc_data"]
|
||||
roc_auc_data = experiment_data["roc_auc_data"]
|
||||
folder = experiment_data["folder"]
|
||||
exp_title = experiment_data["exp_title"]
|
||||
except KeyError as e:
|
||||
print(f"Missing key in experiment data: {e}")
|
||||
raise
|
||||
for evaluation_type in evaluation_types:
|
||||
plt.figure(figsize=(8, 6))
|
||||
for model in models:
|
||||
# Gather all folds' ROC data for this model and evaluation_type
|
||||
fold_rocs = []
|
||||
auc_scores = []
|
||||
for fold_idx in range(k_fold_num):
|
||||
try:
|
||||
fpr, tpr, thresholds = roc_data[model][evaluation_type][fold_idx]
|
||||
fold_rocs.append((fpr, tpr))
|
||||
auc_scores.append(roc_auc_data[model][evaluation_type][fold_idx])
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
if not fold_rocs:
|
||||
print(
|
||||
f"No ROC data for model {model}, evaluation {evaluation_type} in {folder.name}"
|
||||
)
|
||||
continue
|
||||
|
||||
# Interpolate TPRs to a common FPR grid
|
||||
mean_fpr = np.linspace(0, 1, 100)
|
||||
interp_tprs = []
|
||||
for fpr, tpr in fold_rocs:
|
||||
interp_tpr = np.interp(mean_fpr, fpr, tpr)
|
||||
interp_tpr[0] = 0.0
|
||||
interp_tprs.append(interp_tpr)
|
||||
mean_tpr = np.mean(interp_tprs, axis=0)
|
||||
std_tpr = np.std(interp_tprs, axis=0)
|
||||
mean_tpr[-1] = 1.0
|
||||
|
||||
# Mean and CI for AUC
|
||||
mean_auc, auc_ci = confidence_interval(auc_scores)
|
||||
|
||||
# Plot mean ROC and std band
|
||||
plt.plot(
|
||||
mean_fpr,
|
||||
mean_tpr,
|
||||
label=f"{model} (AUC={mean_auc:.2f}±{auc_ci:.2f})",
|
||||
)
|
||||
plt.fill_between(
|
||||
mean_fpr,
|
||||
mean_tpr - std_tpr,
|
||||
mean_tpr + std_tpr,
|
||||
alpha=0.15,
|
||||
)
|
||||
|
||||
plt.plot([0, 1], [0, 1], "k--", label="Chance")
|
||||
plt.xlabel("False Positive Rate")
|
||||
plt.ylabel("True Positive Rate")
|
||||
plt.title(f"ROC Curve ({exp_title} - {evaluation_type})")
|
||||
plt.legend(loc="lower right")
|
||||
plt.tight_layout()
|
||||
plt.savefig(
|
||||
(output_path / f"roc_curve_{folder.name}_{evaluation_type}.png").as_posix()
|
||||
)
|
||||
plt.close()
|
||||
|
||||
|
||||
def main():
|
||||
base_output_path.mkdir(exist_ok=True, parents=True)
|
||||
# Find all subfolders (skip files)
|
||||
subfolders = [f for f in parent_results_path.iterdir() if f.is_dir()]
|
||||
print(f"Found {len(subfolders)} subfolders in {parent_results_path}")
|
||||
all_experiments_data = []
|
||||
for folder in track(
|
||||
subfolders, description="[cyan]Loading data...", total=len(subfolders)
|
||||
):
|
||||
all_experiments_data.append(load_results_data(folder))
|
||||
|
||||
print("Data loading complete. Plotting ROC curves...")
|
||||
roc_curves_output_path = base_output_path / "roc_curves"
|
||||
roc_curves_output_path.mkdir(exist_ok=True, parents=True)
|
||||
for experiment_data in track(
|
||||
all_experiments_data,
|
||||
description="[green]Plotting ROC curves...",
|
||||
total=len(all_experiments_data),
|
||||
):
|
||||
plot_roc_curve(experiment_data, roc_curves_output_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
295
tools/gridsearch_new.py
Normal file
295
tools/gridsearch_new.py
Normal file
@@ -0,0 +1,295 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Grid-search launcher (2-GPU, fixed per-GPU batch sizes)
|
||||
|
||||
• one job at a time per GPU
|
||||
• watchdog heartbeats + error pushes
|
||||
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import itertools
|
||||
import queue
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from os import environ
|
||||
from pathlib import Path
|
||||
|
||||
import GPUtil
|
||||
import requests
|
||||
|
||||
# ─────────────── Watchdog / host configuration ────────────────
|
||||
WATCHDOG_ROOT = "https://mt.the-k.at"
|
||||
BASIC_AUTH = ("jan", "jruuI3GZ@9Rnt7")
|
||||
HEARTBEAT_EVERY = 60
|
||||
HOSTNAME = "gpu-node-01"
|
||||
OUT_FOLDER = Path("./grid_search")
|
||||
DONE_FOLDER = OUT_FOLDER / "done"
|
||||
FAILED_FOLDER = OUT_FOLDER / "failed"
|
||||
|
||||
PING_URL, ERR_URL = f"{WATCHDOG_ROOT}/ping", f"{WATCHDOG_ROOT}/error"
|
||||
HEADERS = {"Content-Type": "application/json"}
|
||||
|
||||
# ───────────────────── Hyper-parameter grid ─────────────────────
|
||||
PARAM_GRID = {
|
||||
"network_name": ["subter_LeNet", "subter_efficient"],
|
||||
"latent_space_dim": [32, 64, 128, 256, 512, 768, 1024],
|
||||
"semi_label": [(0, 0), (50, 10), (500, 100)], # (normal, anomaly)
|
||||
}
|
||||
|
||||
# ────────────────────── FIXED PARAMETERS ──────────────────────
|
||||
BATCH_SIZE = 128 # fixed batch size per GPU
|
||||
EPOCHS_AE = 50 # autoencoder epochs
|
||||
EPOCHS_DEEPSAD = 120 # Deep SAD epochs
|
||||
|
||||
CMD_TEMPLATE = (
|
||||
"python src/main.py train subter {network_name} {exp_folder} "
|
||||
"~/jan/data --k_fold True --k_fold_num 5 "
|
||||
"--num_known_normal {num_known_normal} --num_known_outlier {num_known_anomaly} "
|
||||
"--lr 0.0001 --n_epochs {deepsad_epochs} --lr_milestone 50 --batch_size {batch_size} "
|
||||
"--weight_decay 0.5e-6 --latent_space_dim {latent_space_dim} "
|
||||
"--pretrain True --ae_lr 0.0001 --ae_n_epochs {ae_epochs} --ae_batch_size {batch_size} "
|
||||
"--ae_weight_decay 0.5e-3 --normal_class 0 --known_outlier_class 1 "
|
||||
"--n_known_outlier_classes 1 --seed 3 --device cuda:0"
|
||||
)
|
||||
|
||||
# ──────────────── global bookkeeping / queues ──────────────────
|
||||
STOP_EVT = threading.Event()
|
||||
JOB_TABLE = [] # [{ …, status }]
|
||||
|
||||
|
||||
# ─────────────────────── helper functions ──────────────────────
|
||||
def post_json(url, payload):
|
||||
try:
|
||||
requests.post(
|
||||
url, json=payload, headers=HEADERS, auth=BASIC_AUTH, timeout=5
|
||||
).raise_for_status()
|
||||
except Exception as exc:
|
||||
print(f"[warn] POST {url} failed: {exc}", file=sys.stderr)
|
||||
|
||||
|
||||
def gpu_stats():
|
||||
stats = []
|
||||
for g in GPUtil.getGPUs():
|
||||
stats.append(
|
||||
{
|
||||
"id": g.id,
|
||||
"util": int(g.load * 100),
|
||||
"mem": {"used": int(g.memoryUsed), "total": int(g.memoryTotal)},
|
||||
}
|
||||
)
|
||||
return stats
|
||||
|
||||
|
||||
def summarise_jobs():
|
||||
out = {"pending": 0, "running": 0, "ok": 0, "fail": 0}
|
||||
for j in JOB_TABLE:
|
||||
out[j["status"]] += 1
|
||||
return out
|
||||
|
||||
|
||||
def heartbeater():
|
||||
while not STOP_EVT.wait(HEARTBEAT_EVERY):
|
||||
post_json(
|
||||
PING_URL, {"host": HOSTNAME, "gpu": gpu_stats(), "status": summarise_jobs()}
|
||||
)
|
||||
|
||||
|
||||
# ───────────────────────── worker logic ────────────────────────
|
||||
def worker(device: str, q: "queue.Queue[dict]"):
|
||||
while True:
|
||||
job = q.get()
|
||||
if job is None:
|
||||
break # sentinel for shutdown
|
||||
wait_until_allowed_hours()
|
||||
run_job(job, device)
|
||||
q.task_done()
|
||||
|
||||
|
||||
def exp_folder_name(params):
|
||||
num_norm, num_anom = params["semi_label"]
|
||||
return (
|
||||
f"{params['network_name']}_"
|
||||
f"latent{params['latent_space_dim']}_"
|
||||
f"n{num_norm}_a{num_anom}"
|
||||
)
|
||||
|
||||
|
||||
def move_exp_folder(exp_folder: Path, target_folder: Path):
|
||||
"""Move the experiment folder to the target folder."""
|
||||
destination_folder = target_folder / exp_folder.name
|
||||
if destination_folder.exists():
|
||||
destination_folder.unlink()
|
||||
target_folder.mkdir(parents=True, exist_ok=True)
|
||||
exp_folder.rename(target_folder / exp_folder.name)
|
||||
|
||||
|
||||
def already_done_set():
|
||||
if not DONE_FOLDER.exists():
|
||||
return set()
|
||||
return set([f.name for f in DONE_FOLDER.iterdir() if f.is_dir()])
|
||||
|
||||
|
||||
def run_job(job: dict, device: str):
|
||||
num_norm, num_anom = job["params"]["semi_label"]
|
||||
exp_folder = job["exp_folder"]
|
||||
exp_folder.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
cmd = CMD_TEMPLATE.format(
|
||||
network_name=job["params"]["network_name"],
|
||||
exp_folder=exp_folder.as_posix(),
|
||||
num_known_normal=num_norm,
|
||||
num_known_anomaly=num_anom,
|
||||
latent_space_dim=job["params"]["latent_space_dim"],
|
||||
batch_size=BATCH_SIZE,
|
||||
ae_epochs=EPOCHS_AE,
|
||||
deepsad_epochs=EPOCHS_DEEPSAD,
|
||||
)
|
||||
|
||||
job.update({"device": device, "status": "running", "start": time.time()})
|
||||
post_json(
|
||||
PING_URL, {"host": HOSTNAME, "msg": f"starting {exp_folder.name} on {device}"}
|
||||
)
|
||||
print(f"EXEC [{device}] {cmd}", flush=True)
|
||||
|
||||
try:
|
||||
env = environ.copy()
|
||||
env["CUDA_VISIBLE_DEVICES"] = device.split(":")[1] # "0" or "1"
|
||||
res = subprocess.run(
|
||||
cmd, shell=True, capture_output=True, text=True, env=env, check=False
|
||||
)
|
||||
job.update({"end": time.time(), "returncode": res.returncode})
|
||||
job["status"] = "ok" if res.returncode == 0 else "fail"
|
||||
if res.returncode == 0:
|
||||
move_exp_folder(exp_folder, DONE_FOLDER)
|
||||
else:
|
||||
move_exp_folder(exp_folder, FAILED_FOLDER)
|
||||
tail = (res.stderr or "no-stderr")[-500:]
|
||||
post_json(
|
||||
ERR_URL,
|
||||
{
|
||||
"host": HOSTNAME,
|
||||
"msg": f"rc {res.returncode} {exp_folder.name} → {tail}",
|
||||
},
|
||||
)
|
||||
print(
|
||||
f"ERRR [{device}] rc {res.returncode} {exp_folder.name} → {tail}",
|
||||
flush=True,
|
||||
)
|
||||
except Exception as exc:
|
||||
job.update({"end": time.time(), "status": "fail", "returncode": -999})
|
||||
move_exp_folder(exp_folder, FAILED_FOLDER)
|
||||
post_json(
|
||||
ERR_URL,
|
||||
{"host": HOSTNAME, "msg": f'exception "{exc}" in {exp_folder.name}'},
|
||||
)
|
||||
|
||||
|
||||
# ────────────────────── graceful shutdown ──────────────────────
|
||||
def shutdown(reason):
|
||||
post_json(ERR_URL, {"host": HOSTNAME, "msg": f"run stopped: {reason}"})
|
||||
STOP_EVT.set()
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
for sig in (signal.SIGINT, signal.SIGTERM):
|
||||
signal.signal(sig, lambda s, f, sig=sig: shutdown(signal.Signals(sig).name))
|
||||
|
||||
|
||||
# ─────────────────────────── main() ────────────────────────────
|
||||
def wait_until_allowed_hours():
|
||||
"""Sleep until the current time is between 22:00 and 04:00."""
|
||||
while True:
|
||||
now = datetime.datetime.now()
|
||||
hour = now.hour
|
||||
# Allowed window: 22:00 (22) to 04:00 (4)
|
||||
if hour >= 22 or hour < 4:
|
||||
break
|
||||
# Calculate seconds until 22:00 today or 22:00 tomorrow if after 4am
|
||||
if hour < 22:
|
||||
next_allowed = now.replace(hour=22, minute=0, second=0, microsecond=0)
|
||||
else:
|
||||
# After 4am but before 22:00, so next allowed is tonight
|
||||
next_allowed = now.replace(hour=22, minute=0, second=0, microsecond=0)
|
||||
if next_allowed < now:
|
||||
next_allowed += datetime.timedelta(days=1)
|
||||
wait_seconds = (next_allowed - now).total_seconds()
|
||||
print(f"[info] Waiting until 22:00 to start new jobs ({int(wait_seconds/60)} min)...")
|
||||
time.sleep(min(wait_seconds, 60*10)) # Sleep in chunks of max 10 minutes
|
||||
|
||||
def main():
|
||||
threading.Thread(target=heartbeater, daemon=True).start()
|
||||
|
||||
# two worker queues, one per GPU
|
||||
q0, q1 = queue.Queue(), queue.Queue()
|
||||
threading.Thread(target=worker, args=("cuda:0", q0), daemon=True).start()
|
||||
threading.Thread(target=worker, args=("cuda:1", q1), daemon=True).start()
|
||||
|
||||
# build full parameter combinations as jobs
|
||||
keys = list(PARAM_GRID)
|
||||
jobs = []
|
||||
for combo in itertools.product(*PARAM_GRID.values()):
|
||||
params = dict(zip(keys, combo))
|
||||
exp_folder = OUT_FOLDER / exp_folder_name(params)
|
||||
job = {
|
||||
"params": params,
|
||||
"exp_folder": exp_folder,
|
||||
"status": "pending",
|
||||
"start": None,
|
||||
"end": None,
|
||||
"returncode": None,
|
||||
}
|
||||
jobs.append(job)
|
||||
|
||||
# Check which jobs are already done and mark them
|
||||
done_exps = already_done_set()
|
||||
#print(f"Already done jobs found: {done_exps}")
|
||||
|
||||
for job in jobs:
|
||||
if job["exp_folder"].name in done_exps:
|
||||
job["status"] = "ok"
|
||||
|
||||
# Print summary of job statuses before starting
|
||||
n_done = sum(1 for job in jobs if job["status"] == "ok")
|
||||
n_pending = sum(1 for job in jobs if job["status"] != "ok")
|
||||
print(f"[info] {n_done} jobs already done, {n_pending} jobs pending.")
|
||||
|
||||
# Add all jobs to global JOB_TABLE for bookkeeping
|
||||
JOB_TABLE.extend(jobs)
|
||||
|
||||
# Only enqueue jobs that are not already done
|
||||
for job in jobs:
|
||||
if job["status"] == "ok":
|
||||
continue
|
||||
# Hardcode device assignment
|
||||
if job["params"]["network_name"] == "subter_LeNet":
|
||||
q1.put(job) # cuda:1
|
||||
elif job["params"]["network_name"] == "subter_efficient":
|
||||
q0.put(job) # cuda:0
|
||||
else:
|
||||
# fallback: load-balance
|
||||
(q0 if q0.qsize() <= q1.qsize() else q1).put(job)
|
||||
|
||||
q0.join()
|
||||
q1.join() # wait for all jobs to drain
|
||||
q0.put(None)
|
||||
q1.put(None) # terminate workers
|
||||
STOP_EVT.set()
|
||||
|
||||
post_json(
|
||||
PING_URL,
|
||||
{
|
||||
"host": HOSTNAME,
|
||||
"msg": "all jobs done",
|
||||
"gpu": gpu_stats(),
|
||||
"status": summarise_jobs(),
|
||||
},
|
||||
)
|
||||
print("[info] grid search completed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
339
tools/plot_scripts/ae_elbow_lenet.py
Normal file
339
tools/plot_scripts/ae_elbow_lenet.py
Normal file
@@ -0,0 +1,339 @@
|
||||
import pickle
|
||||
import shutil
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from tabulate import tabulate
|
||||
|
||||
# Configuration
|
||||
results_folders = {
|
||||
"LeNet": {
|
||||
"path": Path(
|
||||
"/home/fedex/mt/projects/thesis-kowalczyk-jan/Deep-SAD-PyTorch/test/DeepSAD/subter_ae_elbow_v2/"
|
||||
),
|
||||
"batch_size": 256,
|
||||
},
|
||||
"LeNet Efficient": {
|
||||
"path": Path(
|
||||
"/home/fedex/mt/projects/thesis-kowalczyk-jan/Deep-SAD-PyTorch/test/DeepSAD/subter_efficient_ae_elbow"
|
||||
),
|
||||
"batch_size": 64,
|
||||
},
|
||||
}
|
||||
output_path = Path("/home/fedex/mt/plots/ae_elbow_lenet")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
|
||||
# Create output directories
|
||||
output_path.mkdir(exist_ok=True, parents=True)
|
||||
output_datetime_path.mkdir(exist_ok=True, parents=True)
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
archive_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
def calculate_batch_mean_loss(scores, batch_size):
|
||||
"""Calculate mean loss over batches similar to the original testing code."""
|
||||
n_samples = len(scores)
|
||||
n_batches = (n_samples + batch_size - 1) // batch_size
|
||||
|
||||
batch_losses = []
|
||||
for i in range(0, n_samples, batch_size):
|
||||
batch_scores = scores[i : i + batch_size]
|
||||
batch_losses.append(np.mean(batch_scores))
|
||||
|
||||
return np.sum(batch_losses) / n_batches
|
||||
|
||||
|
||||
def test_loss_calculation(results, batch_size):
|
||||
"""Test if our loss calculation matches the original implementation."""
|
||||
test = unittest.TestCase()
|
||||
folds = results["ae_results"]
|
||||
dim = results["dimension"]
|
||||
|
||||
for fold_key in folds:
|
||||
fold_data = folds[fold_key]["test"]
|
||||
scores = np.array(fold_data["scores"])
|
||||
original_loss = fold_data["loss"]
|
||||
calculated_loss = calculate_batch_mean_loss(scores, batch_size)
|
||||
|
||||
try:
|
||||
test.assertAlmostEqual(
|
||||
original_loss,
|
||||
calculated_loss,
|
||||
places=5,
|
||||
msg=f"Loss mismatch for dim={dim}, {fold_key}",
|
||||
)
|
||||
except AssertionError as e:
|
||||
print(f"Warning: {str(e)}")
|
||||
print(f"Original: {original_loss:.6f}, Calculated: {calculated_loss:.6f}")
|
||||
raise
|
||||
|
||||
|
||||
def plot_loss_curve(dims, means, stds, title, color, output_path):
|
||||
"""Create and save a single loss curve plot."""
|
||||
plt.figure(figsize=(8, 5))
|
||||
plt.plot(dims, means, marker="o", color=color, label="Mean Test Loss")
|
||||
plt.fill_between(
|
||||
dims,
|
||||
np.array(means) - np.array(stds),
|
||||
np.array(means) + np.array(stds),
|
||||
color=color,
|
||||
alpha=0.2,
|
||||
label="Std Dev",
|
||||
)
|
||||
plt.xlabel("Latent Dimension")
|
||||
plt.ylabel("Test Loss")
|
||||
plt.title(title)
|
||||
plt.legend()
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.xticks(dims)
|
||||
plt.tight_layout()
|
||||
plt.savefig(output_path, dpi=150, bbox_inches="tight")
|
||||
plt.close()
|
||||
|
||||
|
||||
def plot_multi_loss_curve(arch_results, title, output_path, colors=None):
|
||||
"""Create and save a loss curve plot with multiple architectures.
|
||||
|
||||
Args:
|
||||
arch_results: Dict of format {arch_name: (dims, means, stds)}
|
||||
title: Plot title
|
||||
output_path: Where to save the plot
|
||||
colors: Optional dict of colors for each architecture
|
||||
"""
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
if colors is None:
|
||||
colors = {
|
||||
"LeNet": "blue",
|
||||
"LeNet Asymmetric": "red",
|
||||
}
|
||||
|
||||
# Get unique dimensions across all architectures
|
||||
all_dims = sorted(
|
||||
set(dim for _, (dims, _, _) in arch_results.items() for dim in dims)
|
||||
)
|
||||
|
||||
for arch_name, (dims, means, stds) in arch_results.items():
|
||||
color = colors.get(arch_name, "gray")
|
||||
plt.plot(dims, means, marker="o", color=color, label=arch_name)
|
||||
plt.fill_between(
|
||||
dims,
|
||||
np.array(means) - np.array(stds),
|
||||
np.array(means) + np.array(stds),
|
||||
color=color,
|
||||
alpha=0.2,
|
||||
)
|
||||
|
||||
plt.xlabel("Latent Dimension")
|
||||
plt.ylabel("Test Loss")
|
||||
plt.title(title)
|
||||
plt.legend()
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.xticks(all_dims) # Set x-axis ticks to match data points
|
||||
plt.tight_layout()
|
||||
plt.savefig(output_path, dpi=150, bbox_inches="tight")
|
||||
plt.close()
|
||||
|
||||
|
||||
def evaluate_autoencoder_loss():
|
||||
"""Main function to evaluate autoencoder loss across different latent dimensions."""
|
||||
# Results storage for each architecture
|
||||
arch_results = {
|
||||
name: {"dims": [], "normal": [], "anomaly": []} for name in results_folders
|
||||
}
|
||||
|
||||
# Process each architecture
|
||||
for arch_name, config in results_folders.items():
|
||||
results_folder = config["path"]
|
||||
batch_size = config["batch_size"]
|
||||
result_files = sorted(
|
||||
results_folder.glob("ae_elbow_results_subter_*_kfold.pkl")
|
||||
)
|
||||
|
||||
dimensions = []
|
||||
normal_means = []
|
||||
normal_stds = []
|
||||
anomaly_means = []
|
||||
anomaly_stds = []
|
||||
|
||||
# Verify loss calculation
|
||||
print(
|
||||
f"\nVerifying loss calculation for {arch_name} (batch_size={batch_size})..."
|
||||
)
|
||||
for result_file in result_files:
|
||||
with open(result_file, "rb") as f:
|
||||
results = pickle.load(f)
|
||||
test_loss_calculation(results, batch_size)
|
||||
print(f"Loss calculation verified successfully for {arch_name}!")
|
||||
|
||||
# Process files for this architecture
|
||||
for result_file in result_files:
|
||||
with open(result_file, "rb") as f:
|
||||
results = pickle.load(f)
|
||||
dim = int(results["dimension"])
|
||||
folds = results["ae_results"]
|
||||
|
||||
normal_fold_losses = []
|
||||
anomaly_fold_losses = []
|
||||
|
||||
all_scores = [] # Collect all scores for overall calculation
|
||||
all_fold_scores = [] # Collect all fold scores for std calculation
|
||||
|
||||
for fold_key in folds:
|
||||
fold_data = folds[fold_key]["test"]
|
||||
scores = np.array(fold_data["scores"])
|
||||
labels = np.array(fold_data["labels_exp_based"])
|
||||
|
||||
normal_scores = scores[labels == 1]
|
||||
anomaly_scores = scores[labels == -1]
|
||||
|
||||
normal_fold_losses.append(
|
||||
calculate_batch_mean_loss(normal_scores, batch_size)
|
||||
)
|
||||
anomaly_fold_losses.append(
|
||||
calculate_batch_mean_loss(anomaly_scores, batch_size)
|
||||
)
|
||||
|
||||
all_scores.append(scores) # Add scores to all_scores
|
||||
all_fold_scores.append(fold_data["scores"]) # Add fold scores
|
||||
|
||||
dimensions.append(dim)
|
||||
normal_means.append(np.mean(normal_fold_losses))
|
||||
normal_stds.append(np.std(normal_fold_losses))
|
||||
anomaly_means.append(np.mean(anomaly_fold_losses))
|
||||
anomaly_stds.append(np.std(anomaly_fold_losses))
|
||||
|
||||
# Sort by dimension
|
||||
sorted_data = sorted(
|
||||
zip(dimensions, normal_means, normal_stds, anomaly_means, anomaly_stds)
|
||||
)
|
||||
dims, n_means, n_stds, a_means, a_stds = zip(*sorted_data)
|
||||
|
||||
# Store results for this architecture
|
||||
arch_results[arch_name] = {
|
||||
"dims": dims,
|
||||
"normal": (dims, n_means, n_stds),
|
||||
"anomaly": (dims, a_means, a_stds),
|
||||
"overall": (
|
||||
dims,
|
||||
[
|
||||
calculate_batch_mean_loss(scores, batch_size)
|
||||
for scores in all_scores
|
||||
], # Use all scores
|
||||
[
|
||||
np.std(
|
||||
[
|
||||
calculate_batch_mean_loss(fold_scores, batch_size)
|
||||
for fold_scores in fold_scores_list
|
||||
]
|
||||
)
|
||||
for fold_scores_list in all_fold_scores
|
||||
],
|
||||
),
|
||||
}
|
||||
|
||||
# Create the three plots with all architectures
|
||||
plot_multi_loss_curve(
|
||||
{name: results["normal"] for name, results in arch_results.items()},
|
||||
"Normal Class Test Loss vs. Latent Dimension",
|
||||
output_datetime_path / "ae_elbow_test_loss_normal.png",
|
||||
)
|
||||
|
||||
plot_multi_loss_curve(
|
||||
{name: results["anomaly"] for name, results in arch_results.items()},
|
||||
"Anomaly Class Test Loss vs. Latent Dimension",
|
||||
output_datetime_path / "ae_elbow_test_loss_anomaly.png",
|
||||
)
|
||||
|
||||
plot_multi_loss_curve(
|
||||
{name: results["overall"] for name, results in arch_results.items()},
|
||||
"Overall Test Loss vs. Latent Dimension",
|
||||
output_datetime_path / "ae_elbow_test_loss_overall.png",
|
||||
)
|
||||
|
||||
|
||||
def print_loss_comparison(results_folders):
|
||||
"""Print comparison tables of original vs calculated losses for each architecture."""
|
||||
print("\nLoss Comparison Tables")
|
||||
print("=" * 80)
|
||||
|
||||
for arch_name, config in results_folders.items():
|
||||
results_folder = config["path"]
|
||||
batch_size = config["batch_size"]
|
||||
result_files = sorted(
|
||||
results_folder.glob("ae_elbow_results_subter_*_kfold.pkl")
|
||||
)
|
||||
|
||||
# Prepare table data
|
||||
table_data = []
|
||||
headers = ["Dimension", "Original", "Calculated", "Diff"]
|
||||
|
||||
for result_file in result_files:
|
||||
with open(result_file, "rb") as f:
|
||||
results = pickle.load(f)
|
||||
|
||||
dim = int(results["dimension"])
|
||||
folds = results["ae_results"]
|
||||
|
||||
# Calculate mean original loss across folds
|
||||
orig_losses = []
|
||||
calc_losses = []
|
||||
for fold_key in folds:
|
||||
fold_data = folds[fold_key]["test"]
|
||||
orig_losses.append(fold_data["loss"])
|
||||
calc_losses.append(
|
||||
calculate_batch_mean_loss(np.array(fold_data["scores"]), batch_size)
|
||||
)
|
||||
|
||||
orig_mean = np.mean(orig_losses)
|
||||
calc_mean = np.mean(calc_losses)
|
||||
diff = abs(orig_mean - calc_mean)
|
||||
|
||||
table_data.append([dim, orig_mean, calc_mean, diff])
|
||||
|
||||
# Sort by dimension
|
||||
table_data.sort(key=lambda x: x[0])
|
||||
|
||||
print(f"\n{arch_name}:")
|
||||
print(
|
||||
tabulate(
|
||||
table_data,
|
||||
headers=headers,
|
||||
floatfmt=".6f",
|
||||
tablefmt="pipe",
|
||||
numalign="right",
|
||||
)
|
||||
)
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Print loss comparisons for all architectures
|
||||
print_loss_comparison(results_folders)
|
||||
|
||||
# Run main analysis
|
||||
evaluate_autoencoder_loss()
|
||||
|
||||
# Archive management
|
||||
# Delete current latest folder
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# Copy contents to latest folder
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# Copy this script for reference
|
||||
shutil.copy2(__file__, output_datetime_path)
|
||||
shutil.copy2(__file__, latest_folder_path)
|
||||
|
||||
# Move output to archive
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
223
tools/plot_scripts/background_ml_illustrations.py
Normal file
223
tools/plot_scripts/background_ml_illustrations.py
Normal file
@@ -0,0 +1,223 @@
|
||||
"""
|
||||
Downloads the cats_vs_dogs dataset, then generates four PNGs:
|
||||
- supervised_grid.png
|
||||
- unsupervised_clusters.png
|
||||
- semi_supervised_classification.png
|
||||
- semi_supervised_clustering.png
|
||||
"""
|
||||
|
||||
import os
|
||||
import random
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
import tensorflow_datasets as tfds
|
||||
from sklearn.cluster import KMeans
|
||||
from sklearn.decomposition import PCA
|
||||
from sklearn.linear_model import LogisticRegression
|
||||
from sklearn.semi_supervised import LabelSpreading
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# CONFIGURATION
|
||||
# -----------------------------------------------------------------------------
|
||||
NUM_SUPERVISED = 16
|
||||
GRID_ROWS = 4
|
||||
GRID_COLS = 4
|
||||
|
||||
UNSUP_SAMPLES = 200
|
||||
|
||||
# how many labeled points to “seed” semi-sup methods
|
||||
N_LABELED_CLASS = 10 # for classification demo
|
||||
N_SEEDS_PER_CLASS = 3 # for clustering demo
|
||||
|
||||
OUTPUT_DIR = "outputs"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# UTILITIES
|
||||
# -----------------------------------------------------------------------------
|
||||
def ensure_dir(path):
|
||||
os.makedirs(path, exist_ok=True)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 1) Supervised grid
|
||||
# -----------------------------------------------------------------------------
|
||||
def plot_supervised_grid(ds, info, num, rows, cols, outpath):
|
||||
plt.figure(figsize=(cols * 2, rows * 2))
|
||||
for i, (img, lbl) in enumerate(ds.take(num)):
|
||||
ax = plt.subplot(rows, cols, i + 1)
|
||||
ax.imshow(img.numpy().astype("uint8"))
|
||||
ax.axis("off")
|
||||
cname = info.features["label"].int2str(lbl.numpy())
|
||||
ax.set_title(cname, fontsize=9)
|
||||
plt.tight_layout()
|
||||
plt.savefig(outpath, dpi=150)
|
||||
plt.close()
|
||||
print(f"✔ Saved supervised grid → {outpath}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 2) Unsupervised clustering (PCA + KMeans)
|
||||
# -----------------------------------------------------------------------------
|
||||
def plot_unsupervised_clusters(ds, outpath):
|
||||
imgs = []
|
||||
for img, _ in ds.take(UNSUP_SAMPLES):
|
||||
arr = (
|
||||
tf.image.resize(img, (64, 64)).numpy().astype("float32").mean(axis=2)
|
||||
) # resize and grayscale to speed up
|
||||
imgs.append(arr.ravel() / 255.0)
|
||||
X = np.stack(imgs)
|
||||
pca = PCA(n_components=2, random_state=0)
|
||||
X2 = pca.fit_transform(X)
|
||||
|
||||
km = KMeans(n_clusters=2, random_state=0)
|
||||
clusters = km.fit_predict(X2)
|
||||
|
||||
plt.figure(figsize=(6, 6))
|
||||
plt.scatter(X2[:, 0], X2[:, 1], c=clusters, s=15, alpha=0.6)
|
||||
plt.title("Unsupervised: PCA + KMeans")
|
||||
plt.xlabel("PCA 1")
|
||||
plt.ylabel("PCA 2")
|
||||
plt.tight_layout()
|
||||
plt.savefig(outpath, dpi=150)
|
||||
plt.close()
|
||||
print(f"✔ Saved unsupervised clusters → {outpath}")
|
||||
|
||||
return X2, clusters # return for reuse
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 3) Semi‐supervised classification demo
|
||||
# -----------------------------------------------------------------------------
|
||||
def plot_semi_supervised_classification(X2, y_true, outpath):
|
||||
n = X2.shape[0]
|
||||
all_idx = list(range(n))
|
||||
labeled_idx = random.sample(all_idx, N_LABELED_CLASS)
|
||||
unlabeled_idx = list(set(all_idx) - set(labeled_idx))
|
||||
|
||||
# pure supervised
|
||||
clf = LogisticRegression().fit(X2[labeled_idx], y_true[labeled_idx])
|
||||
|
||||
# semi‐supervised
|
||||
y_train = np.full(n, -1, dtype=int)
|
||||
y_train[labeled_idx] = y_true[labeled_idx]
|
||||
ls = LabelSpreading().fit(X2, y_train)
|
||||
|
||||
# grid for decision boundary
|
||||
x_min, x_max = X2[:, 0].min() - 1, X2[:, 0].max() + 1
|
||||
y_min, y_max = X2[:, 1].min() - 1, X2[:, 1].max() + 1
|
||||
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 200), np.linspace(y_min, y_max, 200))
|
||||
grid = np.c_[xx.ravel(), yy.ravel()]
|
||||
pred_sup = clf.predict(grid).reshape(xx.shape)
|
||||
pred_semi = ls.predict(grid).reshape(xx.shape)
|
||||
|
||||
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
|
||||
for ax, Z, title in zip(
|
||||
axes, [pred_sup, pred_semi], ["Supervised only", "Semi-supervised"]
|
||||
):
|
||||
ax.contourf(xx, yy, Z, alpha=0.3)
|
||||
ax.scatter(X2[unlabeled_idx, 0], X2[unlabeled_idx, 1], s=20, alpha=0.4)
|
||||
ax.scatter(
|
||||
X2[labeled_idx, 0],
|
||||
X2[labeled_idx, 1],
|
||||
c=y_true[labeled_idx],
|
||||
s=80,
|
||||
edgecolor="k",
|
||||
)
|
||||
ax.set_title(title)
|
||||
ax.set_xlabel("PCA 1")
|
||||
ax.set_ylabel("PCA 2")
|
||||
plt.tight_layout()
|
||||
plt.savefig(outpath, dpi=150)
|
||||
plt.close()
|
||||
print(f"✔ Saved semi-supervised classification → {outpath}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 4) Semi‐supervised clustering (seeded KMeans)
|
||||
# -----------------------------------------------------------------------------
|
||||
def plot_semi_supervised_clustering(X2, y_true, outpath):
|
||||
# pick a few seeds per class
|
||||
cats = np.where(y_true == 0)[0]
|
||||
dogs = np.where(y_true == 1)[0]
|
||||
seeds = list(np.random.choice(cats, N_SEEDS_PER_CLASS, replace=False)) + list(
|
||||
np.random.choice(dogs, N_SEEDS_PER_CLASS, replace=False)
|
||||
)
|
||||
|
||||
# pure KMeans
|
||||
km1 = KMeans(n_clusters=2, random_state=0).fit(X2)
|
||||
lab1 = km1.labels_
|
||||
|
||||
# seeded: init centers from seed means
|
||||
ctr0 = X2[seeds[:N_SEEDS_PER_CLASS]].mean(axis=0)
|
||||
ctr1 = X2[seeds[N_SEEDS_PER_CLASS:]].mean(axis=0)
|
||||
km2 = KMeans(
|
||||
n_clusters=2, init=np.vstack([ctr0, ctr1]), n_init=1, random_state=0
|
||||
).fit(X2)
|
||||
lab2 = km2.labels_
|
||||
|
||||
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
|
||||
for ax, labels, title in zip(axes, [lab1, lab2], ["Pure KMeans", "Seeded KMeans"]):
|
||||
ax.scatter(X2[:, 0], X2[:, 1], c=labels, s=20, alpha=0.6)
|
||||
ax.scatter(
|
||||
X2[seeds, 0],
|
||||
X2[seeds, 1],
|
||||
c=y_true[seeds],
|
||||
edgecolor="k",
|
||||
marker="x",
|
||||
s=100,
|
||||
linewidths=2,
|
||||
)
|
||||
ax.set_title(title)
|
||||
ax.set_xlabel("PCA 1")
|
||||
ax.set_ylabel("PCA 2")
|
||||
plt.tight_layout()
|
||||
plt.savefig(outpath, dpi=150)
|
||||
plt.close()
|
||||
print(f"✔ Saved semi-supervised clustering → {outpath}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# -----------------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
ensure_dir(OUTPUT_DIR)
|
||||
|
||||
# load
|
||||
print("▶ Loading cats_vs_dogs...")
|
||||
ds, info = tfds.load(
|
||||
"cats_vs_dogs", split="train", with_info=True, as_supervised=True
|
||||
)
|
||||
ds = ds.shuffle(1000, reshuffle_each_iteration=False).cache()
|
||||
|
||||
# supervised
|
||||
plot_supervised_grid(
|
||||
ds,
|
||||
info,
|
||||
NUM_SUPERVISED,
|
||||
GRID_ROWS,
|
||||
GRID_COLS,
|
||||
os.path.join(OUTPUT_DIR, "supervised_grid.png"),
|
||||
)
|
||||
|
||||
# unsupervised
|
||||
# also returns X2 for downstream demos
|
||||
X2, _ = plot_unsupervised_clusters(
|
||||
ds, os.path.join(OUTPUT_DIR, "unsupervised_clusters.png")
|
||||
)
|
||||
|
||||
# collect true labels for that same subset
|
||||
# (we need a y_true array for semi-sup demos)
|
||||
y_true = np.array([lbl.numpy() for _, lbl in ds.take(UNSUP_SAMPLES)])
|
||||
|
||||
# semi-supervised classification
|
||||
plot_semi_supervised_classification(
|
||||
X2, y_true, os.path.join(OUTPUT_DIR, "semi_supervised_classification.png")
|
||||
)
|
||||
|
||||
# semi-supervised clustering
|
||||
plot_semi_supervised_clustering(
|
||||
X2, y_true, os.path.join(OUTPUT_DIR, "semi_supervised_clustering.png")
|
||||
)
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
description = "Python 3.13 devshell with tensorflow-datasets, matplotlib, scikit-learn and numpy";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
...
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
# optional: config = { allowUnfree = true; };
|
||||
};
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
name = "py313-devshell";
|
||||
# bring in the Python 3.13 packages
|
||||
buildInputs =
|
||||
with pkgs;
|
||||
[ python313 ]
|
||||
++ (with pkgs.python313Packages; [
|
||||
tensorflow-datasets
|
||||
matplotlib
|
||||
scikit-learn
|
||||
numpy
|
||||
]);
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
274
tools/plot_scripts/background_ml_semisupervised.py
Normal file
274
tools/plot_scripts/background_ml_semisupervised.py
Normal file
@@ -0,0 +1,274 @@
|
||||
"""
|
||||
Downloads the cats_vs_dogs dataset, extracts deep features using MobileNetV2,
|
||||
then generates two clustering comparison illustrations using two different embedding pipelines:
|
||||
- PCA followed by t-SNE (saved as: semi_supervised_clustering_tsne.png)
|
||||
- PCA followed by UMAP (saved as: semi_supervised_clustering_umap.png)
|
||||
|
||||
Each illustration compares:
|
||||
- Unsupervised clustering using the deep embedding + KMeans
|
||||
- Semi-supervised clustering using Label Spreading with a few labeled seeds
|
||||
|
||||
This script saves outputs in a datetime folder and also copies the latest outputs
|
||||
to a "latest" folder. All versions of the outputs and scripts are archived.
|
||||
"""
|
||||
|
||||
import random
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
import tensorflow_datasets as tfds
|
||||
import umap
|
||||
from scipy.optimize import linear_sum_assignment
|
||||
from sklearn.cluster import KMeans
|
||||
from sklearn.decomposition import PCA
|
||||
from sklearn.manifold import TSNE
|
||||
from sklearn.semi_supervised import LabelSpreading
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# CONFIGURATION
|
||||
# -----------------------------------------------------------------------------
|
||||
UNSUP_SAMPLES = 200 # number of samples to use for the demo
|
||||
N_LABELED_CLASS = 20 # number of labeled seeds for the semi-supervised approach
|
||||
|
||||
output_path = Path("/home/fedex/mt/plots/background_ml_semisupervised")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# UTILITIES
|
||||
# -----------------------------------------------------------------------------
|
||||
def ensure_dir(directory: Path):
|
||||
directory.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
def cluster_accuracy(y_true, y_pred):
|
||||
"""
|
||||
Compute clustering accuracy by determining the optimal mapping
|
||||
between predicted clusters and true labels using the Hungarian algorithm.
|
||||
"""
|
||||
y_true = y_true.astype(np.int64)
|
||||
y_pred = y_pred.astype(np.int64)
|
||||
labels = np.unique(y_true)
|
||||
clusters = np.unique(y_pred)
|
||||
contingency = np.zeros((labels.size, clusters.size), dtype=np.int64)
|
||||
for i, label in enumerate(labels):
|
||||
for j, cluster in enumerate(clusters):
|
||||
contingency[i, j] = np.sum((y_true == label) & (y_pred == cluster))
|
||||
row_ind, col_ind = linear_sum_assignment(-contingency)
|
||||
accuracy = contingency[row_ind, col_ind].sum() / y_true.size
|
||||
return accuracy
|
||||
|
||||
|
||||
def plot_clustering_comparison_embedding(embedding, y_true, outpath, method_name=""):
|
||||
"""
|
||||
Given a 2D data embedding (e.g., from PCA+t-SNE or PCA+UMAP), this function:
|
||||
- Performs unsupervised clustering with KMeans.
|
||||
- Performs semi-supervised clustering with Label Spreading using a few labeled seeds.
|
||||
- Computes accuracy via the Hungarian algorithm.
|
||||
- Plots the decision boundaries from both methods overlaid with the true labels.
|
||||
- Annotates the plot with the accuracy results.
|
||||
|
||||
The 'method_name' is used in the plot title to indicate which embedding is used.
|
||||
"""
|
||||
n = embedding.shape[0]
|
||||
all_idx = list(range(n))
|
||||
labeled_idx = random.sample(all_idx, N_LABELED_CLASS)
|
||||
|
||||
# Unsupervised clustering using KMeans on all embedded data
|
||||
km = KMeans(n_clusters=2, random_state=0).fit(embedding)
|
||||
unsup_pred = km.predict(embedding)
|
||||
unsup_accuracy = cluster_accuracy(y_true, unsup_pred)
|
||||
|
||||
# Create a grid over the space for decision boundaries
|
||||
x_min, x_max = embedding[:, 0].min() - 1, embedding[:, 0].max() + 1
|
||||
y_min, y_max = embedding[:, 1].min() - 1, embedding[:, 1].max() + 1
|
||||
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 200), np.linspace(y_min, y_max, 200))
|
||||
grid = np.c_[xx.ravel(), yy.ravel()]
|
||||
pred_unsup = km.predict(grid).reshape(xx.shape)
|
||||
|
||||
# Semi-supervised clustering using Label Spreading with labeled seeds
|
||||
y_train = np.full(n, -1, dtype=int)
|
||||
y_train[labeled_idx] = y_true[labeled_idx]
|
||||
ls = LabelSpreading().fit(embedding, y_train)
|
||||
semi_pred = ls.predict(embedding)
|
||||
semi_accuracy = cluster_accuracy(y_true, semi_pred)
|
||||
pred_semi = ls.predict(grid).reshape(xx.shape)
|
||||
|
||||
cmap = plt.cm.coolwarm
|
||||
|
||||
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
|
||||
|
||||
# Unsupervised plot:
|
||||
ax = axes[0]
|
||||
ax.contourf(xx, yy, pred_unsup, alpha=0.2, cmap=cmap)
|
||||
sc1 = ax.scatter(
|
||||
embedding[:, 0],
|
||||
embedding[:, 1],
|
||||
c=y_true,
|
||||
cmap=cmap,
|
||||
s=30,
|
||||
alpha=0.8,
|
||||
edgecolor="k",
|
||||
)
|
||||
ax.set_title(
|
||||
f"{method_name}\nUnsupervised (KMeans) - Acc: {unsup_accuracy:.2f}", fontsize=10
|
||||
)
|
||||
ax.set_xlabel("Dim 1")
|
||||
ax.set_ylabel("Dim 2")
|
||||
handles = []
|
||||
for cl in np.unique(y_true):
|
||||
handles.append(
|
||||
plt.Line2D(
|
||||
[],
|
||||
[],
|
||||
marker="o",
|
||||
linestyle="",
|
||||
color=cmap(cl / (np.max(y_true) + 1)),
|
||||
label=f"Class {cl}",
|
||||
markersize=6,
|
||||
)
|
||||
)
|
||||
ax.legend(handles=handles, loc="upper right")
|
||||
|
||||
# Semi-supervised plot:
|
||||
ax = axes[1]
|
||||
ax.contourf(xx, yy, pred_semi, alpha=0.2, cmap=cmap)
|
||||
sc2 = ax.scatter(
|
||||
embedding[:, 0],
|
||||
embedding[:, 1],
|
||||
c=y_true,
|
||||
cmap=cmap,
|
||||
s=30,
|
||||
alpha=0.8,
|
||||
edgecolor="none",
|
||||
)
|
||||
sc3 = ax.scatter(
|
||||
embedding[labeled_idx, 0],
|
||||
embedding[labeled_idx, 1],
|
||||
c=y_true[labeled_idx],
|
||||
cmap=cmap,
|
||||
s=80,
|
||||
edgecolor="k",
|
||||
marker="o",
|
||||
label="Labeled Seeds",
|
||||
)
|
||||
ax.set_title(
|
||||
f"{method_name}\nSemi-Supervised (Label Spreading) - Acc: {semi_accuracy:.2f}",
|
||||
fontsize=10,
|
||||
)
|
||||
ax.set_xlabel("Dim 1")
|
||||
ax.set_ylabel("Dim 2")
|
||||
handles = []
|
||||
for cl in np.unique(y_true):
|
||||
handles.append(
|
||||
plt.Line2D(
|
||||
[],
|
||||
[],
|
||||
marker="o",
|
||||
linestyle="",
|
||||
color=cmap(cl / (np.max(y_true) + 1)),
|
||||
label=f"Class {cl}",
|
||||
markersize=6,
|
||||
)
|
||||
)
|
||||
handles.append(
|
||||
plt.Line2D(
|
||||
[],
|
||||
[],
|
||||
marker="o",
|
||||
linestyle="",
|
||||
color="black",
|
||||
label="Labeled Seed",
|
||||
markersize=8,
|
||||
)
|
||||
)
|
||||
ax.legend(handles=handles, loc="upper right")
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig(outpath, dpi=150)
|
||||
plt.close()
|
||||
print(f"✔ Saved clustering comparison illustration → {outpath}")
|
||||
print(f"Unsupervised Accuracy: {unsup_accuracy:.2f}")
|
||||
print(f"Semi-Supervised Accuracy: {semi_accuracy:.2f}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# MAIN WITH PRE-TRAINED CNN FEATURE EXTRACTION
|
||||
# -----------------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
# Create output directories
|
||||
ensure_dir(output_path)
|
||||
ensure_dir(output_datetime_path)
|
||||
ensure_dir(latest_folder_path)
|
||||
ensure_dir(archive_folder_path)
|
||||
|
||||
print("▶ Loading cats_vs_dogs dataset...")
|
||||
ds, info = tfds.load(
|
||||
"cats_vs_dogs", split="train", with_info=True, as_supervised=True
|
||||
)
|
||||
ds = ds.shuffle(1000, reshuffle_each_iteration=False).cache()
|
||||
|
||||
# Load a pre-trained CNN (MobileNetV2) for feature extraction.
|
||||
cnn_model = tf.keras.applications.MobileNetV2(
|
||||
include_top=False, weights="imagenet", pooling="avg", input_shape=(224, 224, 3)
|
||||
)
|
||||
|
||||
# Extract deep features for all samples.
|
||||
features_list = []
|
||||
labels = []
|
||||
for img, lbl in ds.take(UNSUP_SAMPLES):
|
||||
# Resize to 224x224 and keep 3 channels.
|
||||
img_resized = tf.image.resize(img, (224, 224))
|
||||
# Preprocess the image for MobileNetV2.
|
||||
img_preprocessed = tf.keras.applications.mobilenet_v2.preprocess_input(
|
||||
img_resized
|
||||
)
|
||||
# Expand dims for batch, run through CNN, then squeeze.
|
||||
features = cnn_model(tf.expand_dims(img_preprocessed, axis=0))
|
||||
features = features.numpy().squeeze()
|
||||
features_list.append(features)
|
||||
labels.append(lbl.numpy())
|
||||
X = np.stack(features_list)
|
||||
y_true = np.array(labels)
|
||||
|
||||
# First, apply PCA to reduce dimensionality to 50
|
||||
pca_50 = PCA(n_components=50, random_state=0).fit_transform(X)
|
||||
|
||||
# Then compute embedding with t-SNE
|
||||
from sklearn.manifold import TSNE
|
||||
|
||||
X_tsne = TSNE(n_components=2, random_state=0, init="pca").fit_transform(pca_50)
|
||||
outfile_tsne = output_datetime_path / "semi_supervised_clustering_tsne.png"
|
||||
plot_clustering_comparison_embedding(
|
||||
X_tsne, y_true, outfile_tsne, "CNN + PCA + t-SNE"
|
||||
)
|
||||
|
||||
# Then compute embedding with UMAP
|
||||
X_umap = umap.UMAP(n_components=2, random_state=0).fit_transform(pca_50)
|
||||
outfile_umap = output_datetime_path / "semi_supervised_clustering_umap.png"
|
||||
plot_clustering_comparison_embedding(
|
||||
X_umap, y_true, outfile_umap, "CNN + PCA + UMAP"
|
||||
)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Update the 'latest' results folder: remove previous and copy current outputs
|
||||
# -----------------------------------------------------------------------------
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
ensure_dir(latest_folder_path)
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# Copy this script to preserve the code used for the outputs
|
||||
script_path = Path(__file__)
|
||||
shutil.copy2(script_path, output_datetime_path)
|
||||
shutil.copy2(script_path, latest_folder_path)
|
||||
|
||||
# Archive the outputs
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
99
tools/plot_scripts/background_ml_supervised.py
Normal file
99
tools/plot_scripts/background_ml_supervised.py
Normal file
@@ -0,0 +1,99 @@
|
||||
"""
|
||||
Downloads the cats_vs_dogs dataset, then generates a supervised grid image:
|
||||
- supervised_grid.png
|
||||
|
||||
This script saves outputs in a datetime folder and also copies the latest outputs to a "latest" folder.
|
||||
All versions of the outputs and scripts are archived.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import tensorflow_datasets as tfds
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# CONFIGURATION
|
||||
# -----------------------------------------------------------------------------
|
||||
# Number of supervised samples and grid dimensions
|
||||
NUM_SUPERVISED = 16
|
||||
GRID_ROWS = 4
|
||||
GRID_COLS = 4
|
||||
|
||||
# Output directories for saving plots and scripts
|
||||
output_path = Path("/home/fedex/mt/plots/background_ml_supervised")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# UTILITIES
|
||||
# -----------------------------------------------------------------------------
|
||||
def ensure_dir(directory: Path):
|
||||
directory.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
# Create required output directories
|
||||
ensure_dir(output_path)
|
||||
ensure_dir(output_datetime_path)
|
||||
ensure_dir(latest_folder_path)
|
||||
ensure_dir(archive_folder_path)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Supervised grid plot
|
||||
# -----------------------------------------------------------------------------
|
||||
def plot_supervised_grid(ds, info, num, rows, cols, outpath):
|
||||
"""
|
||||
Plots a grid of images from the dataset with their corresponding labels.
|
||||
"""
|
||||
plt.figure(figsize=(cols * 2, rows * 2))
|
||||
for i, (img, lbl) in enumerate(ds.take(num)):
|
||||
ax = plt.subplot(rows, cols, i + 1)
|
||||
ax.imshow(img.numpy().astype("uint8"))
|
||||
ax.axis("off")
|
||||
cname = info.features["label"].int2str(lbl.numpy())
|
||||
ax.set_title(cname, fontsize=9)
|
||||
plt.tight_layout()
|
||||
plt.savefig(outpath, dpi=150)
|
||||
plt.close()
|
||||
print(f"✔ Saved supervised grid → {outpath}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# -----------------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
# Download and prepare the dataset
|
||||
print("▶ Loading cats_vs_dogs dataset...")
|
||||
ds, info = tfds.load(
|
||||
"cats_vs_dogs", split="train", with_info=True, as_supervised=True
|
||||
)
|
||||
ds = ds.shuffle(1000, reshuffle_each_iteration=False).cache()
|
||||
|
||||
# Generate the supervised grid image
|
||||
supervised_outfile = output_datetime_path / "supervised_grid.png"
|
||||
plot_supervised_grid(
|
||||
ds, info, NUM_SUPERVISED, GRID_ROWS, GRID_COLS, supervised_outfile
|
||||
)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Update the 'latest' results folder: remove previous and copy current outputs
|
||||
# -----------------------------------------------------------------------------
|
||||
import shutil
|
||||
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
ensure_dir(latest_folder_path)
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# Copy this script to the output folder and to the latest folder to preserve the used code
|
||||
script_path = Path(__file__)
|
||||
shutil.copy2(script_path, output_datetime_path)
|
||||
shutil.copy2(script_path, latest_folder_path)
|
||||
|
||||
# Move the output datetime folder to the archive folder for record keeping
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
105
tools/plot_scripts/background_ml_unsupervised.py
Normal file
105
tools/plot_scripts/background_ml_unsupervised.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Downloads the cats_vs_dogs dataset, then generates an unsupervised clusters image:
|
||||
- unsupervised_clusters.png
|
||||
|
||||
This script saves outputs in a datetime folder and also copies the latest outputs to a "latest" folder.
|
||||
All versions of the outputs and scripts are archived.
|
||||
"""
|
||||
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
import tensorflow_datasets as tfds
|
||||
from sklearn.cluster import KMeans
|
||||
from sklearn.decomposition import PCA
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# CONFIGURATION
|
||||
# -----------------------------------------------------------------------------
|
||||
UNSUP_SAMPLES = 200
|
||||
|
||||
output_path = Path("/home/fedex/mt/plots/background_ml_unsupervised")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# UTILITIES
|
||||
# -----------------------------------------------------------------------------
|
||||
def ensure_dir(directory: Path):
|
||||
directory.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
# Create required output directories
|
||||
ensure_dir(output_path)
|
||||
ensure_dir(output_datetime_path)
|
||||
ensure_dir(latest_folder_path)
|
||||
ensure_dir(archive_folder_path)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Unsupervised Clustering Plot (PCA + KMeans)
|
||||
# -----------------------------------------------------------------------------
|
||||
def plot_unsupervised_clusters(ds, outpath):
|
||||
"""
|
||||
Processes a subset of images from the dataset, reduces their dimensionality with PCA,
|
||||
applies KMeans clustering, and saves a scatterplot of the clusters.
|
||||
"""
|
||||
imgs = []
|
||||
for img, _ in ds.take(UNSUP_SAMPLES):
|
||||
# resize to 64x64, convert to grayscale by averaging channels
|
||||
arr = tf.image.resize(img, (64, 64)).numpy().astype("float32").mean(axis=2)
|
||||
imgs.append(arr.ravel() / 255.0)
|
||||
X = np.stack(imgs)
|
||||
pca = PCA(n_components=2, random_state=0)
|
||||
X2 = pca.fit_transform(X)
|
||||
|
||||
km = KMeans(n_clusters=2, random_state=0)
|
||||
clusters = km.fit_predict(X2)
|
||||
|
||||
plt.figure(figsize=(6, 6))
|
||||
plt.scatter(X2[:, 0], X2[:, 1], c=clusters, s=15, alpha=0.6)
|
||||
plt.title("Unsupervised: PCA + KMeans")
|
||||
plt.xlabel("PCA 1")
|
||||
plt.ylabel("PCA 2")
|
||||
plt.tight_layout()
|
||||
plt.savefig(outpath, dpi=150)
|
||||
plt.close()
|
||||
print(f"✔ Saved unsupervised clusters → {outpath}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# -----------------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
# Load and prepare the dataset
|
||||
print("▶ Loading cats_vs_dogs dataset...")
|
||||
ds, _ = tfds.load("cats_vs_dogs", split="train", with_info=True, as_supervised=True)
|
||||
ds = ds.shuffle(1000, reshuffle_each_iteration=False).cache()
|
||||
|
||||
# Generate the unsupervised clusters image
|
||||
unsupervised_outfile = output_datetime_path / "unsupervised_clusters.png"
|
||||
plot_unsupervised_clusters(ds, unsupervised_outfile)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Update the 'latest' results folder: remove previous and copy current outputs
|
||||
# -----------------------------------------------------------------------------
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
ensure_dir(latest_folder_path)
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# Copy this script to the output folder and to the latest folder to preserve the used code
|
||||
script_path = Path(__file__)
|
||||
shutil.copy2(script_path, output_datetime_path)
|
||||
shutil.copy2(script_path, latest_folder_path)
|
||||
|
||||
# Move the output datetime folder to the archive folder for record keeping
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
255
tools/plot_scripts/data_anomalies_timeline.py
Normal file
255
tools/plot_scripts/data_anomalies_timeline.py
Normal file
@@ -0,0 +1,255 @@
|
||||
import json
|
||||
import pickle
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
# define data paths
|
||||
all_data_path = Path("/home/fedex/mt/data/subter")
|
||||
output_path = Path("/home/fedex/mt/plots/data_anomalies_timeline")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
cache_path = output_path
|
||||
|
||||
# if output does not exist, create it
|
||||
output_path.mkdir(exist_ok=True, parents=True)
|
||||
output_datetime_path.mkdir(exist_ok=True, parents=True)
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
archive_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
data_resolution = 32 * 2048
|
||||
|
||||
# find all bag files and sort them correctly by name
|
||||
normal_experiment_paths, anomaly_experiment_paths = [], []
|
||||
for bag_file_path in all_data_path.iterdir():
|
||||
if bag_file_path.suffix != ".bag":
|
||||
continue
|
||||
if "smoke" in bag_file_path.name:
|
||||
anomaly_experiment_paths.append(bag_file_path)
|
||||
else:
|
||||
normal_experiment_paths.append(bag_file_path)
|
||||
|
||||
# Load manually labeled frames
|
||||
with open(
|
||||
cache_path / "manually_labeled_anomaly_frames.json", "r"
|
||||
) as frame_borders_file:
|
||||
manually_labeled_anomaly_frames_json = json.load(frame_borders_file)
|
||||
if not manually_labeled_anomaly_frames_json:
|
||||
print("No manually labeled anomaly frames found. Exiting...")
|
||||
exit(1)
|
||||
manually_labeled_anomaly_frames = {}
|
||||
try:
|
||||
for file in manually_labeled_anomaly_frames_json["files"]:
|
||||
if file["filename"] not in (
|
||||
p.with_suffix(".npy").name for p in anomaly_experiment_paths
|
||||
):
|
||||
print(
|
||||
f"File {file['filename']} from manually labeled frames not found in anomaly experiments. Exiting..."
|
||||
)
|
||||
exit(1)
|
||||
manually_labeled_anomaly_frames[file["filename"]] = (
|
||||
file["semi_target_begin_frame"],
|
||||
file["semi_target_end_frame"],
|
||||
)
|
||||
except KeyError as e:
|
||||
print(f"Missing key in manually labeled frames JSON: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
def plot_combined_timeline(
|
||||
normal_experiment_paths, anomaly_experiment_paths, title, num_bins=50
|
||||
):
|
||||
"""Plot both missing points and near-sensor measurements over normalized timeline"""
|
||||
# Sort experiments by filesize first (to match original processing order)
|
||||
normal_experiment_paths = sorted(
|
||||
normal_experiment_paths, key=lambda path: path.stat().st_size
|
||||
)
|
||||
anomaly_experiment_paths = sorted(
|
||||
anomaly_experiment_paths, key=lambda path: path.stat().st_size
|
||||
)
|
||||
|
||||
# Get largest normal experiment and moving anomaly experiments
|
||||
baseline_path = normal_experiment_paths[-3] # largest normal experiment
|
||||
moving_exp_indices = [
|
||||
i
|
||||
for i, path in enumerate(anomaly_experiment_paths)
|
||||
if "stationary" not in path.name
|
||||
]
|
||||
moving_anomaly_paths = [anomaly_experiment_paths[i] for i in moving_exp_indices]
|
||||
|
||||
# Load missing points data
|
||||
missing_points_cache = Path(cache_path / "missing_points.pkl")
|
||||
if not missing_points_cache.exists():
|
||||
print("Missing points cache not found!")
|
||||
return
|
||||
|
||||
# Load near-sensor data (using 500mm threshold)
|
||||
near_sensor_cache = Path(cache_path / "particles_near_sensor_counts_500.pkl")
|
||||
if not near_sensor_cache.exists():
|
||||
print("Near-sensor measurements cache not found!")
|
||||
return
|
||||
|
||||
# Load both cached datasets
|
||||
with open(missing_points_cache, "rb") as file:
|
||||
missing_points_normal, missing_points_anomaly = pickle.load(file)
|
||||
with open(near_sensor_cache, "rb") as file:
|
||||
near_sensor_normal, near_sensor_anomaly = pickle.load(file)
|
||||
|
||||
# Get data for baseline and moving experiments
|
||||
missing_data = [missing_points_normal[-3]] + [
|
||||
missing_points_anomaly[i] for i in moving_exp_indices
|
||||
]
|
||||
near_sensor_data = [near_sensor_normal[-3]] + [
|
||||
near_sensor_anomaly[i] for i in moving_exp_indices
|
||||
]
|
||||
all_paths = [baseline_path] + moving_anomaly_paths
|
||||
|
||||
# Create figure with two y-axes and dynamic layout
|
||||
fig, ax1 = plt.subplots(figsize=(12, 6), constrained_layout=True)
|
||||
ax2 = ax1.twinx()
|
||||
|
||||
# Color schemes - gray for baseline, colors for anomaly experiments
|
||||
experiment_colors = ["#808080"] + ["#1f77b4", "#ff7f0e", "#2ca02c"] # gray + colors
|
||||
|
||||
# First create custom legend handles for the metrics
|
||||
from matplotlib.lines import Line2D
|
||||
|
||||
metric_legend = [
|
||||
Line2D([0], [0], color="gray", linestyle="-", label="Missing Points"),
|
||||
Line2D([0], [0], color="gray", linestyle="--", label="Near-Sensor (<0.5m)"),
|
||||
Line2D([0], [0], color="gray", linestyle=":", label="Manually Labeled Borders"),
|
||||
]
|
||||
|
||||
# Plot each experiment's data
|
||||
for i, (missing_exp, near_sensor_exp) in enumerate(
|
||||
zip(missing_data, near_sensor_data)
|
||||
):
|
||||
# Get experiment name without the full path
|
||||
exp_name = all_paths[i].stem
|
||||
# Shorten experiment name if needed
|
||||
exp_name = exp_name.replace("experiment_smoke_", "exp_")
|
||||
|
||||
# Convert both to percentages
|
||||
missing_pct = np.array(missing_exp) / data_resolution * 100
|
||||
near_sensor_pct = np.array(near_sensor_exp) / data_resolution * 100
|
||||
|
||||
# Create normalized timeline bins for both
|
||||
exp_len = len(missing_pct)
|
||||
bins = np.linspace(0, exp_len - 1, num_bins)
|
||||
missing_binned = np.zeros(num_bins)
|
||||
near_sensor_binned = np.zeros(num_bins)
|
||||
|
||||
# Bin both datasets
|
||||
for bin_idx in range(num_bins):
|
||||
if bin_idx == num_bins - 1:
|
||||
start_idx = int(bins[bin_idx])
|
||||
end_idx = exp_len
|
||||
else:
|
||||
start_idx = int(bins[bin_idx])
|
||||
end_idx = int(bins[bin_idx + 1])
|
||||
|
||||
missing_binned[bin_idx] = np.mean(missing_pct[start_idx:end_idx])
|
||||
near_sensor_binned[bin_idx] = np.mean(near_sensor_pct[start_idx:end_idx])
|
||||
|
||||
# Plot both metrics with same color but different line styles
|
||||
color = experiment_colors[i]
|
||||
ax1.plot(
|
||||
range(num_bins),
|
||||
missing_binned,
|
||||
color=color,
|
||||
linestyle="-",
|
||||
alpha=0.6,
|
||||
label=exp_name,
|
||||
)
|
||||
ax2.plot(
|
||||
range(num_bins), near_sensor_binned, color=color, linestyle="--", alpha=0.6
|
||||
)
|
||||
|
||||
# Add vertical lines for manually labeled frames if available
|
||||
if all_paths[i].with_suffix(".npy").name in manually_labeled_anomaly_frames:
|
||||
begin_frame, end_frame = manually_labeled_anomaly_frames[
|
||||
all_paths[i].with_suffix(".npy").name
|
||||
]
|
||||
# Convert frame numbers to normalized timeline positions
|
||||
begin_pos = (begin_frame / exp_len) * (num_bins - 1)
|
||||
end_pos = (end_frame / exp_len) * (num_bins - 1)
|
||||
|
||||
# Add vertical lines with matching color and loose dotting
|
||||
ax1.axvline(
|
||||
x=begin_pos,
|
||||
color=color,
|
||||
linestyle=":",
|
||||
alpha=0.6,
|
||||
)
|
||||
ax1.axvline(
|
||||
x=end_pos,
|
||||
color=color,
|
||||
linestyle=":",
|
||||
alpha=0.6,
|
||||
)
|
||||
|
||||
# Customize axes
|
||||
ax1.set_xlabel("Normalized Timeline")
|
||||
ax1.set_xticks(np.linspace(0, num_bins - 1, 5))
|
||||
ax1.set_xticklabels([f"{x:.0f}%" for x in np.linspace(0, 100, 5)])
|
||||
|
||||
ax1.set_ylabel("Missing Points (%)")
|
||||
ax2.set_ylabel("Points with <0.5m Range (%)")
|
||||
|
||||
plt.title(title)
|
||||
|
||||
# Create legends without fixed positions
|
||||
# First get all lines and labels for experiments
|
||||
lines1, labels1 = ax1.get_legend_handles_labels()
|
||||
|
||||
# Combine both legends into one
|
||||
all_handles = (
|
||||
lines1
|
||||
+ [Line2D([0], [0], color="gray", linestyle="-", label="", alpha=0)]
|
||||
+ metric_legend
|
||||
)
|
||||
all_labels = (
|
||||
labels1
|
||||
+ [""]
|
||||
+ ["Missing Points", "Points Near Sensor (<0.5m)", "Manually Labeled Borders"]
|
||||
)
|
||||
|
||||
# Create single legend in top right corner with consistent margins
|
||||
fig.legend(all_handles, all_labels, loc="upper right", borderaxespad=4.8)
|
||||
|
||||
plt.grid(True, alpha=0.3)
|
||||
|
||||
# Save figure letting matplotlib handle the layout
|
||||
plt.savefig(output_datetime_path / "combined_anomalies_timeline.png", dpi=150)
|
||||
plt.close()
|
||||
|
||||
|
||||
# Generate the combined timeline plot
|
||||
plot_combined_timeline(
|
||||
normal_experiment_paths,
|
||||
anomaly_experiment_paths,
|
||||
"Lidar Degradation Indicators Throughout Experiments\n(Baseline and Moving Anomaly Experiments)",
|
||||
)
|
||||
|
||||
# delete current latest folder
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
|
||||
# create new latest folder
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# copy contents of output folder to the latest folder
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# copy this python script to preserve the code used
|
||||
shutil.copy2(__file__, output_datetime_path)
|
||||
shutil.copy2(__file__, latest_folder_path)
|
||||
|
||||
# move output date folder to archive
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
178
tools/plot_scripts/data_icp_rsme.py
Normal file
178
tools/plot_scripts/data_icp_rsme.py
Normal file
@@ -0,0 +1,178 @@
|
||||
import pickle
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import open3d as o3d
|
||||
from pointcloudset import Dataset
|
||||
from pointcloudset.io.pointcloud.open3d import to_open3d
|
||||
from rich.progress import track
|
||||
|
||||
# define data path containing the bag files
|
||||
all_data_path = Path("/home/fedex/mt/data/subter")
|
||||
|
||||
output_path = Path("/home/fedex/mt/plots/data_icp_rmse")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
|
||||
# if output does not exist, create it
|
||||
output_path.mkdir(exist_ok=True, parents=True)
|
||||
output_datetime_path.mkdir(exist_ok=True, parents=True)
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
archive_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# Add cache folder
|
||||
cache_folder = output_path / "cache"
|
||||
cache_folder.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
def get_cache_path(experiment_path: Path) -> Path:
|
||||
"""Convert experiment bag path to cache pkl path"""
|
||||
return cache_folder / f"{experiment_path.stem}.pkl"
|
||||
|
||||
|
||||
# find all bag files and sort them correctly by name (experiments with smoke in the name are anomalies)
|
||||
normal_experiment_paths, anomaly_experiment_paths = [], []
|
||||
for bag_file_path in all_data_path.iterdir():
|
||||
if bag_file_path.suffix != ".bag":
|
||||
continue
|
||||
if "smoke" in bag_file_path.name:
|
||||
anomaly_experiment_paths.append(bag_file_path)
|
||||
else:
|
||||
normal_experiment_paths.append(bag_file_path)
|
||||
|
||||
# sort anomaly and normal experiments by filesize, ascending
|
||||
anomaly_experiment_paths.sort(key=lambda path: path.stat().st_size)
|
||||
normal_experiment_paths.sort(key=lambda path: path.stat().st_size)
|
||||
|
||||
|
||||
def calculate_icp_rmse(experiment_path):
|
||||
"""Calculate ICP RMSE between consecutive frames in an experiment"""
|
||||
cache_path = get_cache_path(experiment_path)
|
||||
|
||||
# Check cache first
|
||||
if cache_path.exists():
|
||||
with open(cache_path, "rb") as file:
|
||||
return pickle.load(file)
|
||||
|
||||
dataset = Dataset.from_file(experiment_path, topic="/ouster/points")
|
||||
rmse_values = []
|
||||
|
||||
# Convert iterator to list for progress tracking
|
||||
pointclouds = list(dataset)
|
||||
|
||||
# Get consecutive pairs of point clouds with progress bar
|
||||
for i in track(
|
||||
range(len(pointclouds) - 1),
|
||||
description=f"Processing {experiment_path.name}",
|
||||
total=len(pointclouds) - 1,
|
||||
):
|
||||
# Get consecutive point clouds and convert to Open3D format
|
||||
source = to_open3d(pointclouds[i])
|
||||
target = to_open3d(pointclouds[i + 1])
|
||||
|
||||
# Apply point-to-point ICP (much faster than point-to-plane)
|
||||
result = o3d.pipelines.registration.registration_icp(
|
||||
source,
|
||||
target,
|
||||
max_correspondence_distance=0.2, # 20cm max correspondence
|
||||
init=np.identity(4), # Identity matrix as initial transformation
|
||||
estimation_method=o3d.pipelines.registration.TransformationEstimationPointToPoint(),
|
||||
criteria=o3d.pipelines.registration.ICPConvergenceCriteria(
|
||||
max_iteration=50
|
||||
),
|
||||
)
|
||||
|
||||
rmse_values.append(result.inlier_rmse)
|
||||
|
||||
# Cache the results
|
||||
with open(cache_path, "wb") as file:
|
||||
pickle.dump(rmse_values, file, protocol=pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
return rmse_values
|
||||
|
||||
|
||||
def plot_statistical_comparison(normal_paths, anomaly_paths, output_path):
|
||||
"""Create statistical comparison plots between normal and anomalous experiments"""
|
||||
# Collect all RMSE values
|
||||
normal_rmse = []
|
||||
anomaly_rmse = []
|
||||
|
||||
print("Loading cached RMSE values...")
|
||||
for path in normal_paths:
|
||||
normal_rmse.extend(calculate_icp_rmse(path))
|
||||
for path in anomaly_paths:
|
||||
anomaly_rmse.extend(calculate_icp_rmse(path))
|
||||
|
||||
# Convert to numpy arrays
|
||||
normal_rmse = np.array(normal_rmse)
|
||||
anomaly_rmse = np.array(anomaly_rmse)
|
||||
|
||||
# Create figure with two subplots side by sidnte
|
||||
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
|
||||
|
||||
# Box plot
|
||||
data = [normal_rmse, anomaly_rmse]
|
||||
ax1.boxplot(data, labels=["Normal", "Anomalous"])
|
||||
ax1.set_ylabel("ICP RMSE (meters)")
|
||||
ax1.set_title("Box Plot Comparison")
|
||||
ax1.grid(True, alpha=0.3)
|
||||
|
||||
# Violin plot
|
||||
ax2.violinplot(data)
|
||||
ax2.set_xticks([1, 2])
|
||||
ax2.set_xticklabels(["Normal", "Anomalous"])
|
||||
ax2.set_ylabel("ICP RMSE (meters)")
|
||||
ax2.set_title("Violin Plot Comparison")
|
||||
ax2.grid(True, alpha=0.3)
|
||||
|
||||
plt.suptitle(
|
||||
"ICP RMSE Statistical Comparison: Normal vs Anomalous Experiments", fontsize=14
|
||||
)
|
||||
plt.tight_layout()
|
||||
|
||||
# Save both linear and log scale versions
|
||||
plt.savefig(output_path / "icp_rmse_distribution_linear.png", dpi=150)
|
||||
|
||||
# Log scale version
|
||||
ax1.set_yscale("log")
|
||||
ax2.set_yscale("log")
|
||||
plt.savefig(output_path / "icp_rmse_distribution_log.png", dpi=150)
|
||||
plt.close()
|
||||
|
||||
# Print some basic statistics
|
||||
print("\nBasic Statistics:")
|
||||
print(
|
||||
f"Normal experiments - mean: {np.mean(normal_rmse):.4f}, std: {np.std(normal_rmse):.4f}"
|
||||
)
|
||||
print(
|
||||
f"Anomaly experiments - mean: {np.mean(anomaly_rmse):.4f}, std: {np.std(anomaly_rmse):.4f}"
|
||||
)
|
||||
|
||||
|
||||
# Replace all plotting code with just this:
|
||||
plot_statistical_comparison(
|
||||
normal_experiment_paths, anomaly_experiment_paths, output_datetime_path
|
||||
)
|
||||
|
||||
# delete current latest folder
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
|
||||
# create new latest folder
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# copy contents of output folder to the latest folder
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# copy this python script to preserve the code used
|
||||
shutil.copy2(__file__, output_datetime_path)
|
||||
shutil.copy2(__file__, latest_folder_path)
|
||||
|
||||
# move output date folder to archive
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
@@ -150,7 +150,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
|
||||
plt.savefig(output_datetime_path / "missing_points_density.png")
|
||||
|
||||
# create another density version which does not plot number of missing points but percentage of measurements that are missing (total number of points is 32*2048)
|
||||
bins = np.linspace(0, 1, 100)
|
||||
bins = np.linspace(0, 0.6, 100)
|
||||
plt.clf()
|
||||
plt.figure(figsize=(10, 5))
|
||||
plt.hist(
|
||||
|
||||
134
tools/plot_scripts/data_missing_points_anomalies.py
Normal file
134
tools/plot_scripts/data_missing_points_anomalies.py
Normal file
@@ -0,0 +1,134 @@
|
||||
import pickle
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from pointcloudset import Dataset
|
||||
|
||||
# define data paths
|
||||
all_data_path = Path("/home/fedex/mt/data/subter")
|
||||
output_path = Path("/home/fedex/mt/plots/data_missing_points_anomalies")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
|
||||
# if output does not exist, create it
|
||||
output_path.mkdir(exist_ok=True, parents=True)
|
||||
output_datetime_path.mkdir(exist_ok=True, parents=True)
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
archive_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
data_resolution = 32 * 2048
|
||||
|
||||
# find all bag files and sort them correctly by name
|
||||
normal_experiment_paths, anomaly_experiment_paths = [], []
|
||||
for bag_file_path in all_data_path.iterdir():
|
||||
if bag_file_path.suffix != ".bag":
|
||||
continue
|
||||
if "smoke" in bag_file_path.name:
|
||||
anomaly_experiment_paths.append(bag_file_path)
|
||||
else:
|
||||
normal_experiment_paths.append(bag_file_path)
|
||||
|
||||
|
||||
def plot_timeline_comparison(anomaly_experiment_paths, title, num_bins=50):
|
||||
"""Plot missing points percentage over normalized timeline for moving anomaly experiments"""
|
||||
# Sort experiments by filesize first (to match original processing order)
|
||||
anomaly_experiment_paths = sorted(
|
||||
anomaly_experiment_paths, key=lambda path: path.stat().st_size
|
||||
)
|
||||
|
||||
# Filter out stationary experiments
|
||||
moving_exp_indices = [
|
||||
i
|
||||
for i, path in enumerate(anomaly_experiment_paths)
|
||||
if "stationary" not in path.name
|
||||
]
|
||||
moving_anomaly_paths = [anomaly_experiment_paths[i] for i in moving_exp_indices]
|
||||
|
||||
# Try to load cached data from original script's location
|
||||
cache_path = Path("/home/fedex/mt/plots/data_missing_points/missing_points.pkl")
|
||||
if not cache_path.exists():
|
||||
print("No cached data found. Please run the original script first.")
|
||||
return
|
||||
|
||||
with open(cache_path, "rb") as file:
|
||||
_, missing_points_anomaly = pickle.load(file)
|
||||
|
||||
# Get data for moving experiments only (using original indices)
|
||||
moving_anomaly_data = [missing_points_anomaly[i] for i in moving_exp_indices]
|
||||
|
||||
# Create figure
|
||||
plt.figure(figsize=(12, 6))
|
||||
|
||||
# Plot each experiment's timeline
|
||||
for i, exp_data in enumerate(moving_anomaly_data):
|
||||
# Convert to percentage
|
||||
percentages = np.array(exp_data) / data_resolution * 100
|
||||
|
||||
# Create normalized timeline bins
|
||||
exp_len = len(percentages)
|
||||
bins = np.linspace(0, exp_len - 1, num_bins)
|
||||
binned_data = np.zeros(num_bins)
|
||||
|
||||
# Bin the data
|
||||
for bin_idx in range(num_bins):
|
||||
if bin_idx == num_bins - 1:
|
||||
start_idx = int(bins[bin_idx])
|
||||
end_idx = exp_len
|
||||
else:
|
||||
start_idx = int(bins[bin_idx])
|
||||
end_idx = int(bins[bin_idx + 1])
|
||||
|
||||
binned_data[bin_idx] = np.mean(percentages[start_idx:end_idx])
|
||||
|
||||
# Plot with slight transparency to show overlaps
|
||||
plt.plot(
|
||||
range(num_bins),
|
||||
binned_data,
|
||||
alpha=0.6,
|
||||
label=f"Experiment {moving_anomaly_paths[i].stem}",
|
||||
)
|
||||
|
||||
plt.title(title)
|
||||
plt.xlabel("Normalized Timeline")
|
||||
# Add percentage ticks on x-axis
|
||||
plt.xticks(
|
||||
np.linspace(0, num_bins - 1, 5), [f"{x:.0f}%" for x in np.linspace(0, 100, 5)]
|
||||
)
|
||||
plt.ylabel("Missing Points (%)")
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.legend()
|
||||
plt.tight_layout()
|
||||
|
||||
# Save the plot
|
||||
plt.savefig(output_datetime_path / "missing_points_timeline.png", dpi=150)
|
||||
plt.close()
|
||||
|
||||
|
||||
# Generate the timeline comparison plot
|
||||
plot_timeline_comparison(
|
||||
anomaly_experiment_paths,
|
||||
"Missing Lidar Measurements Over Time\n(Moving Anomaly Experiments Only)",
|
||||
)
|
||||
|
||||
# delete current latest folder
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
|
||||
# create new latest folder
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# copy contents of output folder to the latest folder
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# copy this python script to preserve the code used
|
||||
shutil.copy2(__file__, output_datetime_path)
|
||||
shutil.copy2(__file__, latest_folder_path)
|
||||
|
||||
# move output date folder to archive
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
149
tools/plot_scripts/data_particles_near_sensor_anomalies.py
Normal file
149
tools/plot_scripts/data_particles_near_sensor_anomalies.py
Normal file
@@ -0,0 +1,149 @@
|
||||
import pickle
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from pointcloudset import Dataset
|
||||
|
||||
# define data paths
|
||||
all_data_path = Path("/home/fedex/mt/data/subter")
|
||||
output_path = Path("/home/fedex/mt/plots/data_particles_near_sensor_anomalies")
|
||||
datetime_folder_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
latest_folder_path = output_path / "latest"
|
||||
archive_folder_path = output_path / "archive"
|
||||
output_datetime_path = output_path / datetime_folder_name
|
||||
|
||||
# if output does not exist, create it
|
||||
output_path.mkdir(exist_ok=True, parents=True)
|
||||
output_datetime_path.mkdir(exist_ok=True, parents=True)
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
archive_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
data_resolution = 32 * 2048
|
||||
|
||||
# find all bag files and sort them correctly by name
|
||||
normal_experiment_paths, anomaly_experiment_paths = [], []
|
||||
for bag_file_path in all_data_path.iterdir():
|
||||
if bag_file_path.suffix != ".bag":
|
||||
continue
|
||||
if "smoke" in bag_file_path.name:
|
||||
anomaly_experiment_paths.append(bag_file_path)
|
||||
else:
|
||||
normal_experiment_paths.append(bag_file_path)
|
||||
|
||||
|
||||
def plot_timeline_comparison(
|
||||
anomaly_experiment_paths, title, range_threshold, num_bins=50
|
||||
):
|
||||
"""Plot near-sensor measurements percentage over normalized timeline for moving anomaly experiments"""
|
||||
# Sort experiments by filesize first (to match original processing order)
|
||||
anomaly_experiment_paths = sorted(
|
||||
anomaly_experiment_paths, key=lambda path: path.stat().st_size
|
||||
)
|
||||
|
||||
# Filter out stationary experiments
|
||||
moving_exp_indices = [
|
||||
i
|
||||
for i, path in enumerate(anomaly_experiment_paths)
|
||||
if "stationary" not in path.name
|
||||
]
|
||||
moving_anomaly_paths = [anomaly_experiment_paths[i] for i in moving_exp_indices]
|
||||
|
||||
# Try to load cached data
|
||||
cache_path = (
|
||||
Path("/home/fedex/mt/plots/data_particles_near_sensor")
|
||||
/ f"particles_near_sensor_counts_{range_threshold}.pkl"
|
||||
)
|
||||
if not cache_path.exists():
|
||||
print(
|
||||
f"No cached data found for range threshold {range_threshold}. Please run the original script first."
|
||||
)
|
||||
return
|
||||
|
||||
with open(cache_path, "rb") as file:
|
||||
_, particles_near_sensor_anomaly = pickle.load(file)
|
||||
|
||||
# Get data for moving experiments only (using original indices)
|
||||
moving_anomaly_data = [particles_near_sensor_anomaly[i] for i in moving_exp_indices]
|
||||
|
||||
# Create figure
|
||||
plt.figure(figsize=(12, 6))
|
||||
|
||||
# Plot each experiment's timeline
|
||||
for i, exp_data in enumerate(moving_anomaly_data):
|
||||
# Convert to percentage
|
||||
percentages = np.array(exp_data) / data_resolution * 100
|
||||
|
||||
# Create normalized timeline bins
|
||||
exp_len = len(percentages)
|
||||
bins = np.linspace(0, exp_len - 1, num_bins)
|
||||
binned_data = np.zeros(num_bins)
|
||||
|
||||
# Bin the data
|
||||
for bin_idx in range(num_bins):
|
||||
if bin_idx == num_bins - 1:
|
||||
start_idx = int(bins[bin_idx])
|
||||
end_idx = exp_len
|
||||
else:
|
||||
start_idx = int(bins[bin_idx])
|
||||
end_idx = int(bins[bin_idx + 1])
|
||||
|
||||
binned_data[bin_idx] = np.mean(percentages[start_idx:end_idx])
|
||||
|
||||
# Plot with slight transparency to show overlaps
|
||||
plt.plot(
|
||||
range(num_bins),
|
||||
binned_data,
|
||||
alpha=0.6,
|
||||
label=f"Experiment {moving_anomaly_paths[i].stem}",
|
||||
)
|
||||
|
||||
plt.title(f"{title}\n(Range Threshold: {range_threshold / 1000:.1f}m)")
|
||||
plt.xlabel("Normalized Timeline")
|
||||
# Add percentage ticks on x-axis
|
||||
plt.xticks(
|
||||
np.linspace(0, num_bins - 1, 5), [f"{x:.0f}%" for x in np.linspace(0, 100, 5)]
|
||||
)
|
||||
plt.ylabel("Near-Sensor Measurements (%)")
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.legend()
|
||||
plt.tight_layout()
|
||||
|
||||
# Save the plot
|
||||
plt.savefig(
|
||||
output_datetime_path
|
||||
/ f"near_sensor_measurements_timeline_{range_threshold}.png",
|
||||
dpi=150,
|
||||
)
|
||||
plt.close()
|
||||
|
||||
|
||||
# Generate timeline comparison plots for each range threshold
|
||||
range_thresholds = [500, 750, 1000, 1250, 1500]
|
||||
for rt in range_thresholds:
|
||||
print(f"Processing range threshold {rt}...")
|
||||
plot_timeline_comparison(
|
||||
anomaly_experiment_paths,
|
||||
"Near-Sensor Lidar Measurements Over Time\n(Moving Anomaly Experiments Only)",
|
||||
rt,
|
||||
)
|
||||
|
||||
# delete current latest folder
|
||||
shutil.rmtree(latest_folder_path, ignore_errors=True)
|
||||
|
||||
# create new latest folder
|
||||
latest_folder_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# copy contents of output folder to the latest folder
|
||||
for file in output_datetime_path.iterdir():
|
||||
shutil.copy2(file, latest_folder_path)
|
||||
|
||||
# copy this python script to preserve the code used
|
||||
shutil.copy2(__file__, output_datetime_path)
|
||||
shutil.copy2(__file__, latest_folder_path)
|
||||
|
||||
# move output date folder to archive
|
||||
shutil.move(output_datetime_path, archive_folder_path)
|
||||
@@ -78,11 +78,19 @@ def plot_tsne_latent_space(normal_data, anomaly_data, title="TSNE of Latent Spac
|
||||
Plot the TSNE representation of the latent space.
|
||||
This function first applies a PCA-based dimensionality reduction for efficiency.
|
||||
"""
|
||||
# Hardcoded variables to choose every nth normal sample and mth anomaly sample
|
||||
n = 10 # Change this value to select every nth normal sample
|
||||
m = 2 # Change this value to select every mth anomaly sample
|
||||
|
||||
# Select every nth normal sample and mth anomaly sample
|
||||
normal_data = normal_data[::n]
|
||||
anomaly_data = anomaly_data[::m]
|
||||
|
||||
# Combine normal and anomaly data
|
||||
combined_data = np.vstack((normal_data, anomaly_data))
|
||||
|
||||
# Initial dimensionality reduction with PCA
|
||||
reduced_data = reduce_dimensionality(combined_data, n_components=50)
|
||||
reduced_data = reduce_dimensionality(combined_data, n_components=100)
|
||||
|
||||
# Apply TSNE transformation on the PCA-reduced data
|
||||
tsne = TSNE(n_components=2, random_state=42)
|
||||
|
||||
172
tools/print_param_counts.py
Normal file
172
tools/print_param_counts.py
Normal file
@@ -0,0 +1,172 @@
|
||||
import pickle
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
results_path = Path("/home/fedex/mt/results/done")
|
||||
|
||||
efficient_paths, lenet_paths = dict(), dict()
|
||||
|
||||
for result_folder in results_path.iterdir():
|
||||
if not result_folder.is_dir():
|
||||
continue
|
||||
if "n0_a0" not in result_folder.name:
|
||||
continue
|
||||
|
||||
if "efficient" in result_folder.name:
|
||||
match = re.search(r"subter_efficient_latent(\d+)_n0_a0", result_folder.name)
|
||||
if match:
|
||||
latent_value = int(match.group(1))
|
||||
else:
|
||||
raise ValueError("Could not extract latent value from string using regex")
|
||||
efficient_paths[latent_value] = result_folder
|
||||
if "LeNet" in result_folder.name:
|
||||
match = re.search(r"subter_LeNet_latent(\d+)_n0_a0", result_folder.name)
|
||||
if match:
|
||||
latent_value = int(match.group(1))
|
||||
else:
|
||||
raise ValueError("Could not extract latent value from string using regex")
|
||||
lenet_paths[latent_value] = result_folder
|
||||
|
||||
"test"
|
||||
"exp_basedmanual_based"
|
||||
"auc"
|
||||
|
||||
results = dict()
|
||||
print("Efficient paths:")
|
||||
latent_dims = set()
|
||||
for latent_value, path in sorted(efficient_paths.items()):
|
||||
latent_dims.add(latent_value)
|
||||
print(f"Latent {latent_value}: {path}")
|
||||
for kfold_idx in range(5):
|
||||
for method in ["deepsad", "ocsvm", "isoforest"]:
|
||||
with open(path / f"results_{method}_{kfold_idx}.pkl", "rb") as f:
|
||||
results.setdefault("efficient", {}).setdefault(
|
||||
latent_value, {}
|
||||
).setdefault(method, {})[kfold_idx] = pickle.load(f)
|
||||
|
||||
print("\nLeNet paths:")
|
||||
for latent_value, path in sorted(lenet_paths.items()):
|
||||
print(f"Latent {latent_value}: {path}")
|
||||
for kfold_idx in range(5):
|
||||
for method in ["deepsad", "ocsvm", "isoforest"]:
|
||||
with open(path / f"results_{method}_{kfold_idx}.pkl", "rb") as f:
|
||||
results.setdefault("lenet", {}).setdefault(latent_value, {}).setdefault(
|
||||
method, {}
|
||||
)[kfold_idx] = pickle.load(f)
|
||||
|
||||
|
||||
for latent_dim in latent_dims:
|
||||
for network in ["efficient", "lenet"]:
|
||||
for method in ["deepsad", "ocsvm", "isoforest"]:
|
||||
if (
|
||||
latent_dim not in results[network]
|
||||
or method not in results[network][latent_dim]
|
||||
):
|
||||
raise ValueError(
|
||||
f"Missing results for {network} with latent {latent_dim} and method {method}"
|
||||
)
|
||||
if method == "deepsad":
|
||||
results[network][latent_dim][method]["mean_auc_exp"] = np.mean(
|
||||
[
|
||||
results[network][latent_dim][method][kfold_idx]["test"][
|
||||
"exp_based"
|
||||
]["auc"]
|
||||
for kfold_idx in range(5)
|
||||
]
|
||||
)
|
||||
results[network][latent_dim][method]["mean_auc_man"] = np.mean(
|
||||
[
|
||||
results[network][latent_dim][method][kfold_idx]["test"][
|
||||
"manual_based"
|
||||
]["auc"]
|
||||
for kfold_idx in range(5)
|
||||
]
|
||||
)
|
||||
else:
|
||||
results[network][latent_dim][method]["mean_auc_exp"] = np.mean(
|
||||
[
|
||||
results[network][latent_dim][method][kfold_idx][
|
||||
"test_auc_exp_based"
|
||||
]
|
||||
for kfold_idx in range(5)
|
||||
]
|
||||
)
|
||||
results[network][latent_dim][method]["mean_auc_man"] = np.mean(
|
||||
[
|
||||
results[network][latent_dim][method][kfold_idx][
|
||||
"test_auc_manual_based"
|
||||
]
|
||||
for kfold_idx in range(5)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def plot_auc_comparison(results, evaluation_type):
|
||||
"""Plot AUC comparison across methods, architectures and latent dimensions.
|
||||
|
||||
Args:
|
||||
results: Dict containing all results
|
||||
evaluation_type: Either 'exp' or 'man' for experiment or manual based evaluation
|
||||
"""
|
||||
plt.figure(figsize=(10, 6))
|
||||
|
||||
# Define markers for methods
|
||||
markers = {"deepsad": "o", "ocsvm": "s", "isoforest": "^"}
|
||||
|
||||
# Define base colors for architectures and method-specific lightness
|
||||
base_colors = {
|
||||
"efficient": "#1f77b4", # blue
|
||||
"lenet": "#d62728", # red
|
||||
}
|
||||
# Different alpha values for methods
|
||||
method_alphas = {
|
||||
"deepsad": 1.0, # full intensity
|
||||
"ocsvm": 0.7, # slightly lighter
|
||||
"isoforest": 0.4, # even lighter
|
||||
}
|
||||
|
||||
# Get all latent dimensions
|
||||
latent_dims = sorted(list(results["efficient"].keys()))
|
||||
|
||||
# Plot each method and architecture combination
|
||||
for network in ["efficient", "lenet"]:
|
||||
for method in ["deepsad", "ocsvm", "isoforest"]:
|
||||
auc_values = [
|
||||
results[network][dim][method][f"mean_auc_{evaluation_type}"]
|
||||
for dim in latent_dims
|
||||
]
|
||||
|
||||
plt.plot(
|
||||
latent_dims,
|
||||
auc_values,
|
||||
marker=markers[method],
|
||||
color=base_colors[network],
|
||||
alpha=method_alphas[method],
|
||||
linestyle="-" if network == "efficient" else "--",
|
||||
label=f"{network.capitalize()} {method.upper()}",
|
||||
markersize=8,
|
||||
)
|
||||
|
||||
plt.xlabel("Latent Dimension")
|
||||
plt.ylabel("Mean AUC")
|
||||
if evaluation_type == "exp":
|
||||
plt.title("AUC Comparison (Experiment Based Evaluation Labels)")
|
||||
else:
|
||||
plt.title("AUC Comparison (Manual Based Evaluation Labels)")
|
||||
plt.grid(True, alpha=0.3)
|
||||
plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
|
||||
plt.xticks(latent_dims)
|
||||
plt.tight_layout()
|
||||
return plt.gcf()
|
||||
|
||||
|
||||
# Create and save both plots
|
||||
for eval_type in ["exp", "man"]:
|
||||
fig = plot_auc_comparison(results, eval_type)
|
||||
fig.savefig(
|
||||
f"auc_comp/auc_comparison_{eval_type}_based.png", dpi=300, bbox_inches="tight"
|
||||
)
|
||||
plt.close(fig)
|
||||
Reference in New Issue
Block a user