tools, lockfile, deps
This commit is contained in:
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" },
|
||||
]
|
||||
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
|
||||
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")
|
||||
)
|
||||
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)
|
||||
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)
|
||||
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