29 Commits

Author SHA1 Message Date
26682f1741 remove simulation
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in 18s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2025-01-16 22:12:31 -07:00
f1f6c0d45b rearrange readme 2025-01-16 21:55:46 -07:00
e0c42766bf flake8
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in 20s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2025-01-16 21:53:55 -07:00
0202163f08 gui working with real data
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in 17s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2025-01-16 21:50:35 -07:00
18a1b2faa3 better tx tone
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in 40s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2025-01-15 23:01:10 -07:00
c034cdcb95 document firmware versions 2025-01-15 22:59:29 -07:00
0c152c337e make vna.py importable 2025-01-15 22:23:54 -07:00
22a33c2b84 some config stuff 2025-01-15 22:14:27 -07:00
3369bb290a remove debugging print
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in 37s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-21 13:17:16 -07:00
322b5ebc9b don't reformat all the lines on every re-draw 2024-12-21 13:15:15 -07:00
014c742e0a smith too 2024-12-21 13:11:06 -07:00
6d920c6809 plotting with random data 2024-12-21 13:09:56 -07:00
2f7b9fc1eb urls
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -41s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-19 00:55:27 -07:00
134f5b45d7 fix homepage url
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -42s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-19 00:46:43 -07:00
f35d9a85a6 nothing important
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -42s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-19 00:28:20 -07:00
5650e7b03b start cli
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -42s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-19 00:25:47 -07:00
76886011bb partially fix formatting
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -43s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-19 00:07:05 -07:00
528de3b4cc auto-formatting tools 2024-12-19 00:04:51 -07:00
1256c71fac remove unused imports 2024-12-19 00:03:56 -07:00
d637fb73ee more better shortcuts
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -40s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 23:59:45 -07:00
5c4f7e5c97 fix entry point
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -41s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 23:55:06 -07:00
919101b339 Oops. I broke typing
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -42s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 23:50:05 -07:00
67a1864837 util improvements
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -41s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 23:38:45 -07:00
eca933ccef update readme 2024-12-18 23:34:56 -07:00
a5b391e757 untested: add some plot update stuff
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -38s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 23:31:34 -07:00
34a4532a02 more gui stuff
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -42s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 22:52:12 -07:00
98f40179e1 menu stuff
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -41s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 22:35:16 -07:00
5a7bc985b4 start making gui
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -31s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-18 21:37:57 -07:00
f4c099c1d2 update README.md
All checks were successful
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Successful in -14s
Publish Python 🐍 distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been skipped
2024-12-08 13:53:31 -07:00
10 changed files with 1068 additions and 375 deletions

View File

@ -9,6 +9,9 @@ charon-vna = {file = ".", editable = true}
[dev-packages] [dev-packages]
ipykernel = "*" ipykernel = "*"
ipywidgets = "*" ipywidgets = "*"
black = "*"
flake8 = "*"
isort = "*"
[requires] [requires]
python_version = "3.10" python_version = "3.10"

633
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "8ca47bc9e64405da418625530ed3861fbf72ff2f615aa4053f0da928dd09a494" "sha256": "470252a74774400955ef60d73f7e697760609be00b7733aa7a51b2f192e37fe5"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -36,74 +36,63 @@
}, },
"contourpy": { "contourpy": {
"hashes": [ "hashes": [
"sha256:00ccd0dbaad6d804ab259820fa7cb0b8036bda0686ef844d24125d8287178ce0", "sha256:041b640d4ec01922083645a94bb3b2e777e6b626788f4095cf21abbe266413c1",
"sha256:0be4d8425bfa755e0fd76ee1e019636ccc7c29f77a7c86b4328a9eb6a26d0639", "sha256:05e806338bfeaa006acbdeba0ad681a10be63b26e1b17317bfac3c5d98f36cda",
"sha256:0dce35502151b6bd35027ac39ba6e5a44be13a68f55735c3612c568cac3805fd", "sha256:08d9d449a61cf53033612cb368f3a1b26cd7835d9b8cd326647efe43bca7568d",
"sha256:0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad", "sha256:0ffa84be8e0bd33410b17189f7164c3589c229ce5db85798076a3fa136d0e509",
"sha256:14e262f67bd7e6eb6880bc564dcda30b15e351a594657e55b7eec94b6ef72843", "sha256:113231fe3825ebf6f15eaa8bc1f5b0ddc19d42b733345eae0934cb291beb88b6",
"sha256:167d6c890815e1dac9536dca00828b445d5d0df4d6a8c6adb4a7ec3166812fa8", "sha256:14c102b0eab282427b662cb590f2e9340a9d91a1c297f48729431f2dcd16e14f",
"sha256:1ec4dc6bf570f5b22ed0d7efba0dfa9c5b9e0431aeea7581aa217542d9e809a4", "sha256:174e758c66bbc1c8576992cec9599ce8b6672b741b5d336b5c74e35ac382b18e",
"sha256:303c252947ab4b14c08afeb52375b26781ccd6a5ccd81abcdfc1fafd14cf93c1", "sha256:19c1555a6801c2f084c7ddc1c6e11f02eb6a6016ca1318dd5452ba3f613a1751",
"sha256:31cd3a85dbdf1fc002280c65caa7e2b5f65e4a973fcdf70dd2fdcb9868069294", "sha256:19d40d37c1c3a4961b4619dd9d77b12124a453cc3d02bb31a07d58ef684d3d86",
"sha256:32b238b3b3b649e09ce9aaf51f0c261d38644bdfa35cbaf7b263457850957a84", "sha256:1bf98051f1045b15c87868dbaea84f92408337d4f81d0e449ee41920ea121d3b",
"sha256:33c92cdae89ec5135d036e7218e69b0bb2851206077251f04a6c4e0e21f03927", "sha256:20914c8c973f41456337652a6eeca26d2148aa96dd7ac323b74516988bea89fc",
"sha256:345af746d7766821d05d72cb8f3845dfd08dd137101a2cb9b24de277d716def8", "sha256:287ccc248c9e0d0566934e7d606201abd74761b5703d804ff3df8935f523d546",
"sha256:3634b5385c6716c258d0419c46d05c8aa7dc8cb70326c9a4fb66b69ad2b52e09", "sha256:2ba94a401342fc0f8b948e57d977557fbf4d515f03c67682dd5c6191cb2d16ec",
"sha256:364174c2a76057feef647c802652f00953b575723062560498dc7930fc9b1cb7", "sha256:31c1b55c1f34f80557d3830d3dd93ba722ce7e33a0b472cba0ec3b6535684d8f",
"sha256:36e0cff201bcb17a0a8ecc7f454fe078437fa6bda730e695a92f2d9932bd507f", "sha256:36987a15e8ace5f58d4d5da9dca82d498c2bbb28dff6e5d04fbfcc35a9cb3a82",
"sha256:36f965570cff02b874773c49bfe85562b47030805d7d8360748f3eca570f4cab", "sha256:3a04ecd68acbd77fa2d39723ceca4c3197cb2969633836ced1bea14e219d077c",
"sha256:3bb3808858a9dc68f6f03d319acd5f1b8a337e6cdda197f02f4b8ff67ad2057b", "sha256:3e8b974d8db2c5610fb4e76307e265de0edb655ae8169e8b21f41807ccbeec4b",
"sha256:3e1c7fa44aaae40a2247e2e8e0627f4bea3dd257014764aa644f319a5f8600e3", "sha256:3ea9924d28fc5586bf0b42d15f590b10c224117e74409dd7a0be3b62b74a501c",
"sha256:3faeb2998e4fcb256542e8a926d08da08977f7f5e62cf733f3c211c2a5586223", "sha256:4318af1c925fb9a4fb190559ef3eec206845f63e80fb603d47f2d6d67683901c",
"sha256:420d39daa61aab1221567b42eecb01112908b2cab7f1b4106a52caaec8d36973", "sha256:44a29502ca9c7b5ba389e620d44f2fbe792b1fb5734e8b931ad307071ec58c53",
"sha256:4553c421929ec95fb07b3aaca0fae668b2eb5a5203d1217ca7c34c063c53d087", "sha256:47734d7073fb4590b4a40122b35917cd77be5722d80683b249dac1de266aac80",
"sha256:4865cd1d419e0c7a7bf6de1777b185eebdc51470800a9f42b9e9decf17762081", "sha256:4d76d5993a34ef3df5181ba3c92fabb93f1eaa5729504fb03423fcd9f3177242",
"sha256:4cfb5c62ce023dfc410d6059c936dcf96442ba40814aefbfa575425a3a7f19dc", "sha256:4dbbc03a40f916a8420e420d63e96a1258d3d1b58cbdfd8d1f07b49fcbd38e85",
"sha256:4d63ee447261e963af02642ffcb864e5a2ee4cbfd78080657a9880b8b1868e18", "sha256:500360b77259914f7805af7462e41f9cb7ca92ad38e9f94d6c8641b089338124",
"sha256:570ef7cf892f0afbe5b2ee410c507ce12e15a5fa91017a0009f79f7d93a1268f", "sha256:523a8ee12edfa36f6d2a49407f705a6ef4c5098de4f498619787e272de93f2d5",
"sha256:637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d", "sha256:573abb30e0e05bf31ed067d2f82500ecfdaec15627a59d63ea2d95714790f5c2",
"sha256:68a32389b06b82c2fdd68276148d7b9275b5f5cf13e5417e4252f6d1a34f72a2", "sha256:5b75aa69cb4d6f137b36f7eb2ace9280cfb60c55dc5f61c731fdf6f037f958a3",
"sha256:69375194457ad0fad3a839b9e29aa0b0ed53bb54db1bfb6c3ae43d111c31ce41", "sha256:61332c87493b00091423e747ea78200659dc09bdf7fd69edd5e98cef5d3e9a8d",
"sha256:6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67", "sha256:805617228ba7e2cbbfb6c503858e626ab528ac2a32a04a2fe88ffaf6b02c32bc",
"sha256:710a26b3dc80c0e4febf04555de66f5fd17e9cf7170a7b08000601a10570bda6", "sha256:841ad858cff65c2c04bf93875e384ccb82b654574a6d7f30453a04f04af71342",
"sha256:732896af21716b29ab3e988d4ce14bc5133733b85956316fb0c56355f398099b", "sha256:89785bb2a1980c1bd87f0cb1517a71cde374776a5f150936b82580ae6ead44a1",
"sha256:75ee7cb1a14c617f34a51d11fa7524173e56551646828353c4af859c56b766e2", "sha256:8eb96e79b9f3dcadbad2a3891672f81cdcab7f95b27f28f1c67d75f045b6b4f1",
"sha256:76a896b2f195b57db25d6b44e7e03f221d32fe318d03ede41f8b4d9ba1bff53c", "sha256:974d8145f8ca354498005b5b981165b74a195abfae9a8129df3e56771961d595",
"sha256:76c905ef940a4474a6289c71d53122a4f77766eef23c03cd57016ce19d0f7b42", "sha256:9ddeb796389dadcd884c7eb07bd14ef12408aaae358f0e2ae24114d797eede30",
"sha256:7a52040312b1a858b5e31ef28c2e865376a386c60c0e248370bbea2d3f3b760d", "sha256:a045f341a77b77e1c5de31e74e966537bba9f3c4099b35bf4c2e3939dd54cdab",
"sha256:7ffa0db17717a8ffb127efd0c95a4362d996b892c2904db72428d5b52e1938a4", "sha256:a0cffcbede75c059f535725c1680dfb17b6ba8753f0c74b14e6a9c68c29d7ea3",
"sha256:81cb5ed4952aae6014bc9d0421dec7c5835c9c8c31cdf51910b708f548cf58e5", "sha256:a761d9ccfc5e2ecd1bf05534eda382aa14c3e4f9205ba5b1684ecfe400716ef2",
"sha256:834e0cfe17ba12f79963861e0f908556b2cedd52e1f75e6578801febcc6a9f49", "sha256:a7895f46d47671fa7ceec40f31fae721da51ad34bdca0bee83e38870b1f47ffd",
"sha256:87ddffef1dbe5e669b5c2440b643d3fdd8622a348fe1983fad7a0f0ccb1cd67b", "sha256:a9fa36448e6a3a1a9a2ba23c02012c43ed88905ec80163f2ffe2421c7192a5d7",
"sha256:880ea32e5c774634f9fcd46504bf9f080a41ad855f4fef54f5380f5133d343c7", "sha256:ab29962927945d89d9b293eabd0d59aea28d887d4f3be6c22deaefbb938a7277",
"sha256:8ca947601224119117f7c19c9cdf6b3ab54c5726ef1d906aa4a69dfb6dd58102", "sha256:abbb49fb7dac584e5abc6636b7b2a7227111c4f771005853e7d25176daaf8453",
"sha256:90f73a5116ad1ba7174341ef3ea5c3150ddf20b024b98fb0c3b29034752c8aeb", "sha256:ac4578ac281983f63b400f7fe6c101bedc10651650eef012be1ccffcbacf3697",
"sha256:92f8557cbb07415a4d6fa191f20fd9d2d9eb9c0b61d1b2f52a8926e43c6e9af7", "sha256:adce39d67c0edf383647a3a007de0a45fd1b08dedaa5318404f1a73059c2512b",
"sha256:94e848a6b83da10898cbf1311a815f770acc9b6a3f2d646f330d57eb4e87592e", "sha256:ade08d343436a94e633db932e7e8407fe7de8083967962b46bdfc1b0ced39454",
"sha256:9c0da700bf58f6e0b65312d0a5e695179a71d0163957fa381bb3c1f72972537c", "sha256:b2bdca22a27e35f16794cf585832e542123296b4687f9fd96822db6bae17bfc9",
"sha256:a11077e395f67ffc2c44ec2418cfebed032cd6da3022a94fc227b6faf8e2acb8", "sha256:b2f926efda994cdf3c8d3fdb40b9962f86edbc4457e739277b961eced3d0b4c1",
"sha256:aea348f053c645100612b333adc5983d87be69acdc6d77d3169c090d3b01dc35", "sha256:b457d6430833cee8e4b8e9b6f07aa1c161e5e0d52e118dc102c8f9bd7dd060d6",
"sha256:b11b39aea6be6764f84360fce6c82211a9db32a7c7de8fa6dd5397cf1d079c3b", "sha256:c414fc1ed8ee1dbd5da626cf3710c6013d3d27456651d156711fa24f24bd1291",
"sha256:c6c7c2408b7048082932cf4e641fa3b8ca848259212f51c8c59c45aa7ac18f14", "sha256:cb76c1a154b83991a3cbbf0dfeb26ec2833ad56f95540b442c73950af2013750",
"sha256:c6ec93afeb848a0845a18989da3beca3eec2c0f852322efe21af1931147d12cb", "sha256:dfd97abd83335045a913e3bcc4a09c0ceadbe66580cf573fe961f4a825efa699",
"sha256:cacd81e2d4b6f89c9f8a5b69b86490152ff39afc58a95af002a398273e5ce589", "sha256:e914a8cb05ce5c809dd0fe350cfbb4e881bde5e2a38dc04e3afe1b3e58bd158e",
"sha256:d402880b84df3bec6eab53cd0cf802cae6a2ef9537e70cf75e91618a3801c20c", "sha256:ece6df05e2c41bd46776fbc712e0996f7c94e0d0543af1656956d150c4ca7c81",
"sha256:d51fca85f9f7ad0b65b4b9fe800406d0d77017d7270d31ec3fb1cc07358fdea0", "sha256:efa874e87e4a647fd2e4f514d5e91c7d493697127beb95e77d2f7561f6905bd9",
"sha256:d73f659398a0904e125280836ae6f88ba9b178b2fed6884f3b1f95b989d2c8da", "sha256:f611e628ef06670df83fce17805c344710ca5cde01edfdc72751311da8585375"
"sha256:d78ab28a03c854a873787a0a42254a0ccb3cb133c672f645c9f9c8f3ae9d0800",
"sha256:da84c537cb8b97d153e9fb208c221c45605f73147bd4cadd23bdae915042aad6",
"sha256:dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66",
"sha256:e12968fdfd5bb45ffdf6192a590bd8ddd3ba9e58360b29683c6bb71a7b41edca",
"sha256:e1fd23e9d01591bab45546c089ae89d926917a66dceb3abcf01f6105d927e2cb",
"sha256:e8134301d7e204c88ed7ab50028ba06c683000040ede1d617298611f9dc6240c",
"sha256:eb8b141bb00fa977d9122636b16aa67d37fd40a3d8b52dd837e536d64b9a4d06",
"sha256:eca7e17a65f72a5133bdbec9ecf22401c62bcf4821361ef7811faee695799779",
"sha256:f317576606de89da6b7e0861cf6061f6146ead3528acabff9236458a6ba467f8",
"sha256:fd2a0fc506eccaaa7595b7e1418951f213cf8255be2600f1ea1b61e46a60c55f",
"sha256:fe41b41505a5a33aeaed2a613dccaeaa74e0e3ead6dd6fd3a118fb471644fd6c"
], ],
"markers": "python_version >= '3.9'", "markers": "python_version >= '3.10'",
"version": "==1.3.0" "version": "==1.3.1"
}, },
"cycler": { "cycler": {
"hashes": [ "hashes": [
@ -123,57 +112,59 @@
}, },
"fonttools": { "fonttools": {
"hashes": [ "hashes": [
"sha256:07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6", "sha256:07f8288aacf0a38d174445fc78377a97fb0b83cfe352a90c9d9c1400571963c7",
"sha256:0a911591200114969befa7f2cb74ac148bce5a91df5645443371aba6d222e263", "sha256:11e5de1ee0d95af4ae23c1a138b184b7f06e0b6abacabf1d0db41c90b03d834b",
"sha256:0d1d353ef198c422515a3e974a1e8d5b304cd54a4c2eebcae708e37cd9eeffb1", "sha256:1bc7ad24ff98846282eef1cbeac05d013c2154f977a79886bb943015d2b1b261",
"sha256:0e88e3018ac809b9662615072dcd6b84dca4c2d991c6d66e1970a112503bba7e", "sha256:1dcc07934a2165ccdc3a5a608db56fb3c24b609658a5b340aee4ecf3ba679dc0",
"sha256:1d152d1be65652fc65e695e5619e0aa0982295a95a9b29b52b85775243c06556", "sha256:22f38464daa6cdb7b6aebd14ab06609328fe1e9705bb0fcc7d1e69de7109ee02",
"sha256:262705b1663f18c04250bd1242b0515d3bbae177bee7752be67c979b7d47f43d", "sha256:27e4ae3592e62eba83cd2c4ccd9462dcfa603ff78e09110680a5444c6925d841",
"sha256:278913a168f90d53378c20c23b80f4e599dca62fbffae4cc620c8eed476b723e", "sha256:3983313c2a04d6cc1fe9251f8fc647754cf49a61dac6cb1e7249ae67afaafc45",
"sha256:301540e89cf4ce89d462eb23a89464fef50915255ece765d10eee8b2bf9d75b2", "sha256:529cef2ce91dc44f8e407cc567fae6e49a1786f2fefefa73a294704c415322a4",
"sha256:31c32d7d4b0958600eac75eaf524b7b7cb68d3a8c196635252b7a2c30d80e986", "sha256:5323a22eabddf4b24f66d26894f1229261021dacd9d29e89f7872dd8c63f0b8b",
"sha256:357cacb988a18aace66e5e55fe1247f2ee706e01debc4b1a20d77400354cddeb", "sha256:54153c49913f45065c8d9e6d0c101396725c5621c8aee744719300f79771d75a",
"sha256:37cddd62d83dc4f72f7c3f3c2bcf2697e89a30efb152079896544a93907733bd", "sha256:546565028e244a701f73df6d8dd6be489d01617863ec0c6a42fa25bf45d43048",
"sha256:41bb0b250c8132b2fcac148e2e9198e62ff06f3cc472065dff839327945c5882", "sha256:5480673f599ad410695ca2ddef2dfefe9df779a9a5cda89503881e503c9c7d90",
"sha256:4aa4817f0031206e637d1e685251ac61be64d1adef111060df84fdcbc6ab6c44", "sha256:5e8d657cd7326eeaba27de2740e847c6b39dde2f8d7cd7cc56f6aad404ddf0bd",
"sha256:4e10d2e0a12e18f4e2dd031e1bf7c3d7017be5c8dbe524d07706179f355c5dac", "sha256:62d65a3022c35e404d19ca14f291c89cc5890032ff04f6c17af0bd1927299674",
"sha256:5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20", "sha256:6314bf82c54c53c71805318fcf6786d986461622dd926d92a465199ff54b1b72",
"sha256:54471032f7cb5fca694b5f1a0aaeba4af6e10ae989df408e0216f7fd6cdc405d", "sha256:7a8aa2c5e5b8b3bcb2e4538d929f6589a5c6bdb84fd16e2ed92649fb5454f11c",
"sha256:58974b4987b2a71ee08ade1e7f47f410c367cdfc5a94fabd599c88165f56213a", "sha256:827e95fdbbd3e51f8b459af5ea10ecb4e30af50221ca103bea68218e9615de07",
"sha256:58d29b9a294573d8319f16f2f79e42428ba9b6480442fa1836e4eb89c4d9d61c", "sha256:859c358ebf41db18fb72342d3080bce67c02b39e86b9fbcf1610cca14984841b",
"sha256:5eb2474a7c5be8a5331146758debb2669bf5635c021aee00fd7c353558fc659d", "sha256:86721fbc389ef5cc1e2f477019e5069e8e4421e8d9576e9c26f840dbb04678de",
"sha256:6e37561751b017cf5c40fce0d90fd9e8274716de327ec4ffb0df957160be3bff", "sha256:89bdc5d88bdeec1b15af790810e267e8332d92561dce4f0748c2b95c9bdf3926",
"sha256:76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7", "sha256:8c4491699bad88efe95772543cd49870cf756b019ad56294f6498982408ab03e",
"sha256:7965af9b67dd546e52afcf2e38641b5be956d68c425bef2158e95af11d229f10", "sha256:8c5ec45428edaa7022f1c949a632a6f298edc7b481312fc7dc258921e9399628",
"sha256:7e3b7d44e18c085fd8c16dcc6f1ad6c61b71ff463636fcb13df7b1b818bd0c02", "sha256:8e75f12c82127486fac2d8bfbf5bf058202f54bf4f158d367e41647b972342ca",
"sha256:7ed7ee041ff7b34cc62f07545e55e1468808691dddfd315d51dd82a6b37ddef2", "sha256:a430178ad3e650e695167cb53242dae3477b35c95bef6525b074d87493c4bf29",
"sha256:82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07", "sha256:a8c2794ded89399cc2169c4d0bf7941247b8d5932b2659e09834adfbb01589aa",
"sha256:8583e563df41fdecef31b793b4dd3af8a9caa03397be648945ad32717a92885b", "sha256:aca318b77f23523309eec4475d1fbbb00a6b133eb766a8bdc401faba91261abe",
"sha256:8fa92cb248e573daab8d032919623cc309c005086d743afb014c836636166f08", "sha256:ae3b6600565b2d80b7c05acb8e24d2b26ac407b27a3f2e078229721ba5698427",
"sha256:93d458c8a6a354dc8b48fc78d66d2a8a90b941f7fec30e94c7ad9982b1fa6bab", "sha256:aedbeb1db64496d098e6be92b2e63b5fac4e53b1b92032dfc6988e1ea9134a4d",
"sha256:957f669d4922f92c171ba01bef7f29410668db09f6c02111e22b2bce446f3285", "sha256:aee3b57643827e237ff6ec6d28d9ff9766bd8b21e08cd13bff479e13d4b14765",
"sha256:9dc080e5a1c3b2656caff2ac2633d009b3a9ff7b5e93d0452f40cd76d3da3b3c", "sha256:b54baf65c52952db65df39fcd4820668d0ef4766c0ccdf32879b77f7c804d5c5",
"sha256:9ef1b167e22709b46bf8168368b7b5d3efeaaa746c6d39661c1b4405b6352e58", "sha256:b586ab5b15b6097f2fb71cafa3c98edfd0dba1ad8027229e7b1e204a58b0e09d",
"sha256:a7a310c6e0471602fe3bf8efaf193d396ea561486aeaa7adc1f132e02d30c4b9", "sha256:b8d5e8916c0970fbc0f6f1bece0063363bb5857a7f170121a4493e31c3db3314",
"sha256:ab774fa225238986218a463f3fe151e04d8c25d7de09df7f0f5fce27b1243dbc", "sha256:bc5dbb4685e51235ef487e4bd501ddfc49be5aede5e40f4cefcccabc6e60fb4b",
"sha256:ada215fd079e23e060157aab12eba0d66704316547f334eee9ff26f8c0d7b8ab", "sha256:bdcc9f04b36c6c20978d3f060e5323a43f6222accc4e7fcbef3f428e216d96af",
"sha256:c39287f5c8f4a0c5a55daf9eaf9ccd223ea59eed3f6d467133cc727d7b943a55", "sha256:c3ca99e0d460eff46e033cd3992a969658c3169ffcd533e0a39c63a38beb6831",
"sha256:c9c563351ddc230725c4bdf7d9e1e92cbe6ae8553942bd1fb2b2ff0884e8b714", "sha256:caf8230f3e10f8f5d7593eb6d252a37caf58c480b19a17e250a63dad63834cf3",
"sha256:d26732ae002cc3d2ecab04897bb02ae3f11f06dd7575d1df46acd2f7c012a8d8", "sha256:cd70de1a52a8ee2d1877b6293af8a2484ac82514f10b1c67c1c5762d38073e56",
"sha256:d3b659d1029946f4ff9b6183984578041b520ce0f8fb7078bb37ec7445806b33", "sha256:cf4fe7c124aa3f4e4c1940880156e13f2f4d98170d35c749e6b4f119a872551e",
"sha256:dd9cc95b8d6e27d01e1e1f1fae8559ef3c02c76317da650a19047f249acd519d", "sha256:d342e88764fb201286d185093781bf6628bbe380a913c24adf772d901baa8276",
"sha256:e4564cf40cebcb53f3dc825e85910bf54835e8a8b6880d59e5159f0f325e637e", "sha256:da9da6d65cd7aa6b0f806556f4985bcbf603bf0c5c590e61b43aa3e5a0f822d0",
"sha256:e7d82b9e56716ed32574ee106cabca80992e6bbdcf25a88d97d21f73a0aae664", "sha256:dc5294a3d5c84226e3dbba1b6f61d7ad813a8c0238fceea4e09aa04848c3d851",
"sha256:e8a4b261c1ef91e7188a30571be6ad98d1c6d9fa2427244c545e2fa0a2494dd7", "sha256:dd68c87a2bfe37c5b33bcda0fba39b65a353876d3b9006fde3adae31f97b3ef5",
"sha256:e96bc94c8cda58f577277d4a71f51c8e2129b8b36fd05adece6320dd3d57de8a", "sha256:e6e8766eeeb2de759e862004aa11a9ea3d6f6d5ec710551a88b476192b64fd54",
"sha256:ed2f80ca07025551636c555dec2b755dd005e2ea8fbeb99fc5cdff319b70b23b", "sha256:e894b5bd60d9f473bed7a8f506515549cc194de08064d829464088d23097331b",
"sha256:f5b8a096e649768c2f4233f947cf9737f8dbf8728b90e2771e2497c6e3d21d13", "sha256:eb6ca911c4c17eb51853143624d8dc87cdcdf12a711fc38bf5bd21521e79715f",
"sha256:f8e953cc0bddc2beaf3a3c3b5dd9ab7554677da72dfaf46951e193c9653e515a", "sha256:ed63959d00b61959b035c7d47f9313c2c1ece090ff63afea702fe86de00dbed4",
"sha256:fda582236fee135d4daeca056c8c88ec5f6f6d88a004a79b84a02547c8f57386", "sha256:f412604ccbeee81b091b420272841e5ec5ef68967a9790e80bffd0e30b8e2977",
"sha256:fdb062893fd6d47b527d39346e0c5578b7957dcea6d6a3b6794569370013d9ac" "sha256:f7d66c15ba875432a2d2fb419523f5d3d347f91f48f57b8b08a2dfc3c39b8a3f",
"sha256:f9e736f60f4911061235603a6119e72053073a12c6d7904011df2d8fad2c0e35",
"sha256:fb594b5a99943042c702c550d5494bdd7577f6ef19b0bc73877c948a63184a32"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==4.54.1" "version": "==4.55.3"
}, },
"kiwisolver": { "kiwisolver": {
"hashes": [ "hashes": [
@ -297,49 +288,43 @@
}, },
"matplotlib": { "matplotlib": {
"hashes": [ "hashes": [
"sha256:039082812cacd6c6bec8e17a9c1e6baca230d4116d522e81e1f63a74d01d2e21", "sha256:01d2b19f13aeec2e759414d3bfe19ddfb16b13a1250add08d46d5ff6f9be83c6",
"sha256:03ba9c1299c920964e8d3857ba27173b4dbb51ca4bab47ffc2c2ba0eb5e2cbc5", "sha256:12eaf48463b472c3c0f8dbacdbf906e573013df81a0ab82f0616ea4b11281908",
"sha256:050598c2b29e0b9832cde72bcf97627bf00262adbc4a54e2b856426bb2ef0697", "sha256:2c5829a5a1dd5a71f0e31e6e8bb449bc0ee9dbfb05ad28fc0c6b55101b3a4be6",
"sha256:18128cc08f0d3cfff10b76baa2f296fc28c4607368a8402de61bb3f2eb33c7d9", "sha256:2fbbabc82fde51391c4da5006f965e36d86d95f6ee83fb594b279564a4c5d0d2",
"sha256:1cd93b91ab47a3616b4d3c42b52f8363b88ca021e340804c6ab2536344fad9ca", "sha256:3547d153d70233a8496859097ef0312212e2689cdf8d7ed764441c77604095ae",
"sha256:1d94ff717eb2bd0b58fe66380bd8b14ac35f48a98e7c6765117fe67fb7684e64", "sha256:359f87baedb1f836ce307f0e850d12bb5f1936f70d035561f90d41d305fdacea",
"sha256:306c8dfc73239f0e72ac50e5a9cf19cc4e8e331dd0c54f5e69ca8758550f1e1e", "sha256:3b427392354d10975c1d0f4ee18aa5844640b512d5311ef32efd4dd7db106ede",
"sha256:37e51dd1c2db16ede9cfd7b5cabdfc818b2c6397c83f8b10e0e797501c963a03", "sha256:4659665bc7c9b58f8c00317c3c2a299f7f258eeae5a5d56b4c64226fca2f7c59",
"sha256:3fd595f34aa8a55b7fc8bf9ebea8aa665a84c82d275190a61118d33fbc82ccae", "sha256:4673ff67a36152c48ddeaf1135e74ce0d4bce1bbf836ae40ed39c29edf7e2765",
"sha256:4876d7d40219e8ae8bb70f9263bcbe5714415acfdf781086601211335e24f8aa", "sha256:503feb23bd8c8acc75541548a1d709c059b7184cde26314896e10a9f14df5f12",
"sha256:5413401594cfaff0052f9d8b1aafc6d305b4bd7c4331dccd18f561ff7e1d3bd3", "sha256:5439f4c5a3e2e8eab18e2f8c3ef929772fd5641876db71f08127eed95ab64683",
"sha256:5816b1e1fe8c192cbc013f8f3e3368ac56fbecf02fb41b8f8559303f24c5015e", "sha256:5cdbaf909887373c3e094b0318d7ff230b2ad9dcb64da7ade654182872ab2593",
"sha256:65aacf95b62272d568044531e41de26285d54aec8cb859031f511f84bd8b495a", "sha256:5e6c6461e1fc63df30bf6f80f0b93f5b6784299f721bc28530477acd51bfc3d1",
"sha256:6758baae2ed64f2331d4fd19be38b7b4eae3ecec210049a26b6a4f3ae1c85dcc", "sha256:5fd41b0ec7ee45cd960a8e71aea7c946a28a0b8a4dcee47d2856b2af051f334c",
"sha256:6d1ce5ed2aefcdce11904fc5bbea7d9c21fff3d5f543841edf3dea84451a09ea", "sha256:607b16c8a73943df110f99ee2e940b8a1cbf9714b65307c040d422558397dac5",
"sha256:6d9f07a80deab4bb0b82858a9e9ad53d1382fd122be8cde11080f4e7dfedb38b", "sha256:7e8632baebb058555ac0cde75db885c61f1212e47723d63921879806b40bec6a",
"sha256:7741f26a58a240f43bee74965c4882b6c93df3e7eb3de160126d8c8f53a6ae6e", "sha256:81713dd0d103b379de4516b861d964b1d789a144103277769238c732229d7f03",
"sha256:8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447", "sha256:845d96568ec873be63f25fa80e9e7fae4be854a66a7e2f0c8ccc99e94a8bd4ef",
"sha256:909645cce2dc28b735674ce0931a4ac94e12f5b13f6bb0b5a5e65e7cea2c192b", "sha256:95b710fea129c76d30be72c3b38f330269363fbc6e570a5dd43580487380b5ff",
"sha256:96ab43906269ca64a6366934106fa01534454a69e471b7bf3d79083981aaab92", "sha256:96f2886f5c1e466f21cc41b70c5a0cd47bfa0015eb2d5793c88ebce658600e25",
"sha256:9d78bbc0cbc891ad55b4f39a48c22182e9bdaea7fc0e5dbd364f49f729ca1bbb", "sha256:994c07b9d9fe8d25951e3202a68c17900679274dadfc1248738dcfa1bd40d7f3",
"sha256:ab68d50c06938ef28681073327795c5db99bb4666214d2d5f880ed11aeaded66", "sha256:9ade1003376731a971e398cc4ef38bb83ee8caf0aee46ac6daa4b0506db1fd06",
"sha256:ac43031375a65c3196bee99f6001e7fa5bdfb00ddf43379d3c0609bdca042df9", "sha256:9b0558bae37f154fffda54d779a592bc97ca8b4701f1c710055b609a3bac44c8",
"sha256:ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7", "sha256:a2a43cbefe22d653ab34bb55d42384ed30f611bcbdea1f8d7f431011a2e1c62e",
"sha256:b2696efdc08648536efd4e1601b5fd491fd47f4db97a5fbfd175549a7365c1b2", "sha256:a994f29e968ca002b50982b27168addfd65f0105610b6be7fa515ca4b5307c95",
"sha256:b82c5045cebcecd8496a4d694d43f9cc84aeeb49fe2133e036b207abe73f4d30", "sha256:ad2e15300530c1a94c63cfa546e3b7864bd18ea2901317bae8bbf06a5ade6dcf",
"sha256:be0fc24a5e4531ae4d8e858a1a548c1fe33b176bb13eff7f9d0d38ce5112a27d", "sha256:ae80dc3a4add4665cf2faa90138384a7ffe2a4e37c58d83e115b54287c4f06ef",
"sha256:bf81de2926c2db243c9b2cbc3917619a0fc85796c6ba4e58f541df814bbf83c7", "sha256:b886d02a581b96704c9d1ffe55709e49b4d2d52709ccebc4be42db856e511278",
"sha256:c375cc72229614632c87355366bdf2570c2dac01ac66b8ad048d2dabadf2d0d4", "sha256:c40ba2eb08b3f5de88152c2333c58cee7edcead0a2a0d60fcafa116b17117adc",
"sha256:c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41", "sha256:c55b20591ced744aa04e8c3e4b7543ea4d650b6c3c4b208c08a05b4010e8b442",
"sha256:cef2a73d06601437be399908cf13aee74e86932a5ccc6ccdf173408ebc5f6bb2", "sha256:c58a9622d5dbeb668f407f35f4e6bfac34bb9ecdcc81680c04d0258169747997",
"sha256:d52a3b618cb1cbb769ce2ee1dcdb333c3ab6e823944e9a2d36e37253815f9556", "sha256:d44cb942af1693cced2604c33a9abcef6205601c445f6d0dc531d813af8a2f5a",
"sha256:d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f", "sha256:d907fddb39f923d011875452ff1eca29a9e7f21722b873e90db32e5d8ddff12e",
"sha256:d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772", "sha256:fd44fc75522f58612ec4a33958a7e5552562b7705b42ef1b4f8c0818e304a363"
"sha256:dbe196377a8248972f5cede786d4c5508ed5f5ca4a1e09b44bda889958b33f8c",
"sha256:e0830e188029c14e891fadd99702fd90d317df294c3298aad682739c5533721a",
"sha256:f053c40f94bc51bc03832a41b4f153d83f2062d88c72b5e79997072594e97e51",
"sha256:f32c7410c7f246838a77d6d1eff0c0f87f3cb0e7c4247aebea71a6d5a68cab49",
"sha256:f6ee45bc4245533111ced13f1f2cace1e7f89d1c793390392a80c139d6cf0e6c",
"sha256:f7c0410f181a531ec4e93bbc27692f2c71a15c2da16766f5ba9761e7ae518413"
], ],
"markers": "python_version >= '3.9'", "markers": "python_version >= '3.10'",
"version": "==3.9.2" "version": "==3.10.0"
}, },
"numcodecs": { "numcodecs": {
"hashes": [ "hashes": [
@ -366,11 +351,64 @@
}, },
"numpy": { "numpy": {
"hashes": [ "hashes": [
"sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098", "sha256:0557eebc699c1c34cccdd8c3778c9294e8196df27d713706895edc6f57d29608",
"sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761" "sha256:0798b138c291d792f8ea40fe3768610f3c7dd2574389e37c3f26573757c8f7ef",
"sha256:0da8495970f6b101ddd0c38ace92edea30e7e12b9a926b57f5fabb1ecc25bb90",
"sha256:0f0986e917aca18f7a567b812ef7ca9391288e2acb7a4308aa9d265bd724bdae",
"sha256:122fd2fcfafdefc889c64ad99c228d5a1f9692c3a83f56c292618a59aa60ae83",
"sha256:140dd80ff8981a583a60980be1a655068f8adebf7a45a06a6858c873fcdcd4a0",
"sha256:16757cf28621e43e252c560d25b15f18a2f11da94fea344bf26c599b9cf54b73",
"sha256:18142b497d70a34b01642b9feabb70156311b326fdddd875a9981f34a369b671",
"sha256:1c92113619f7b272838b8d6702a7f8ebe5edea0df48166c47929611d0b4dea69",
"sha256:1e25507d85da11ff5066269d0bd25d06e0a0f2e908415534f3e603d2a78e4ffa",
"sha256:30bf971c12e4365153afb31fc73f441d4da157153f3400b82db32d04de1e4066",
"sha256:3579eaeb5e07f3ded59298ce22b65f877a86ba8e9fe701f5576c99bb17c283da",
"sha256:36b2b43146f646642b425dd2027730f99bac962618ec2052932157e213a040e9",
"sha256:3905a5fffcc23e597ee4d9fb3fcd209bd658c352657548db7316e810ca80458e",
"sha256:3a4199f519e57d517ebd48cb76b36c82da0360781c6a0353e64c0cac30ecaad3",
"sha256:3f2f5cddeaa4424a0a118924b988746db6ffa8565e5829b1841a8a3bd73eb59a",
"sha256:40deb10198bbaa531509aad0cd2f9fadb26c8b94070831e2208e7df543562b74",
"sha256:440cfb3db4c5029775803794f8638fbdbf71ec702caf32735f53b008e1eaece3",
"sha256:4723a50e1523e1de4fccd1b9a6dcea750c2102461e9a02b2ac55ffeae09a4410",
"sha256:4bddbaa30d78c86329b26bd6aaaea06b1e47444da99eddac7bf1e2fab717bd72",
"sha256:4e58666988605e251d42c2818c7d3d8991555381be26399303053b58a5bbf30d",
"sha256:54dc1d6d66f8d37843ed281773c7174f03bf7ad826523f73435deb88ba60d2d4",
"sha256:57fcc997ffc0bef234b8875a54d4058afa92b0b0c4223fc1f62f24b3b5e86038",
"sha256:58b92a5828bd4d9aa0952492b7de803135038de47343b2aa3cc23f3b71a3dc4e",
"sha256:5a145e956b374e72ad1dff82779177d4a3c62bc8248f41b80cb5122e68f22d13",
"sha256:6ab153263a7c5ccaf6dfe7e53447b74f77789f28ecb278c3b5d49db7ece10d6d",
"sha256:7832f9e8eb00be32f15fdfb9a981d6955ea9adc8574c521d48710171b6c55e95",
"sha256:7fe4bb0695fe986a9e4deec3b6857003b4cfe5c5e4aac0b95f6a658c14635e31",
"sha256:7fe8f3583e0607ad4e43a954e35c1748b553bfe9fdac8635c02058023277d1b3",
"sha256:85ad7d11b309bd132d74397fcf2920933c9d1dc865487128f5c03d580f2c3d03",
"sha256:9874bc2ff574c40ab7a5cbb7464bf9b045d617e36754a7bc93f933d52bd9ffc6",
"sha256:a184288538e6ad699cbe6b24859206e38ce5fba28f3bcfa51c90d0502c1582b2",
"sha256:a222d764352c773aa5ebde02dd84dba3279c81c6db2e482d62a3fa54e5ece69b",
"sha256:a50aeff71d0f97b6450d33940c7181b08be1441c6c193e678211bff11aa725e7",
"sha256:a55dc7a7f0b6198b07ec0cd445fbb98b05234e8b00c5ac4874a63372ba98d4ab",
"sha256:a62eb442011776e4036af5c8b1a00b706c5bc02dc15eb5344b0c750428c94219",
"sha256:a7d41d1612c1a82b64697e894b75db6758d4f21c3ec069d841e60ebe54b5b571",
"sha256:a98f6f20465e7618c83252c02041517bd2f7ea29be5378f09667a8f654a5918d",
"sha256:afe8fb968743d40435c3827632fd36c5fbde633b0423da7692e426529b1759b1",
"sha256:b0b227dcff8cdc3efbce66d4e50891f04d0a387cce282fe1e66199146a6a8fca",
"sha256:b30042fe92dbd79f1ba7f6898fada10bdaad1847c44f2dff9a16147e00a93661",
"sha256:b606b1aaf802e6468c2608c65ff7ece53eae1a6874b3765f69b8ceb20c5fa78e",
"sha256:b6207dc8fb3c8cb5668e885cef9ec7f70189bec4e276f0ff70d5aa078d32c88e",
"sha256:c2aed8fcf8abc3020d6a9ccb31dbc9e7d7819c56a348cc88fd44be269b37427e",
"sha256:cb24cca1968b21355cc6f3da1a20cd1cebd8a023e3c5b09b432444617949085a",
"sha256:cff210198bb4cae3f3c100444c5eaa573a823f05c253e7188e1362a5555235b3",
"sha256:d35717333b39d1b6bb8433fa758a55f1081543de527171543a2b710551d40881",
"sha256:df12a1f99b99f569a7c2ae59aa2d31724e8d835fc7f33e14f4792e3071d11221",
"sha256:e09d40edfdb4e260cb1567d8ae770ccf3b8b7e9f0d9b5c2a9992696b30ce2742",
"sha256:e12c6c1ce84628c52d6367863773f7c8c8241be554e8b79686e91a43f1733773",
"sha256:e2b8cd48a9942ed3f85b95ca4105c45758438c7ed28fff1e4ce3e57c3b589d8e",
"sha256:e500aba968a48e9019e42c0c199b7ec0696a97fa69037bea163b55398e390529",
"sha256:ebe5e59545401fbb1b24da76f006ab19734ae71e703cdb4a8b347e84a0cece67",
"sha256:f0dd071b95bbca244f4cb7f70b77d2ff3aaaba7fa16dc41f58d14854a6204e6c",
"sha256:f8c8b141ef9699ae777c6278b52c706b653bf15d135d302754f6b2e90eb30367"
], ],
"markers": "python_version >= '3.10'", "markers": "python_version >= '3.10'",
"version": "==2.1.3" "version": "==2.2.0"
}, },
"packaging": { "packaging": {
"hashes": [ "hashes": [
@ -532,6 +570,36 @@
"markers": "python_version >= '3.9'", "markers": "python_version >= '3.9'",
"version": "==3.2.0" "version": "==3.2.0"
}, },
"pyside6": {
"hashes": [
"sha256:6d1fd95651cdbdea741af21e155350986eca31ff015fc4c721ce01c2a110a4cc",
"sha256:7d6adc5d53313249bbe02edb673877c1d437e215d71e88da78412520653f5c9f",
"sha256:866eeaca3ffead6b9d30fa3ed395d5624da0246d7586c8b8207e77ac65d82458",
"sha256:ddeeaeca8ebd0ddb1ded30dd33e9240a40f330cc91832de346ba6c9d0cd1253e"
],
"markers": "python_version < '3.14' and python_version >= '3.9'",
"version": "==6.8.1"
},
"pyside6-addons": {
"hashes": [
"sha256:570a25016d80046274f454ed0bb06734f478ce6c21be5dec62b624773fc7504e",
"sha256:879c12346b4b76f5d5ee6499d8ca53b5666c0c998b8fdf8780f08f69ea95d6f9",
"sha256:d7c8c1e89ee0db84631d5b8fdb9129d9d2a0ffb3b4cb2f5192dc8367dd980db4",
"sha256:f80cc03c1ac54132c6f800aa461dced64acd7d1646898db164ccb56fe3c23dd4"
],
"markers": "python_version < '3.14' and python_version >= '3.9'",
"version": "==6.8.1"
},
"pyside6-essentials": {
"hashes": [
"sha256:2f600b149e65b57acd6a444edb17615adc42cc2491548ae443ccb574036d86b1",
"sha256:bd05155245e3cd1572e68d72772e78fadfd713575bbfdd2c5e060d5278e390e9",
"sha256:bf8a3c9ee0b997eb18fb00cb09aacaa28b8a51ce3c295a252cc594c5530aba56",
"sha256:d5ed4ddb149f36d65bc49ae4260b2d213ee88b2d9a309012ae27f38158c2d1b6"
],
"markers": "python_version < '3.14' and python_version >= '3.9'",
"version": "==6.8.1"
},
"python-dateutil": { "python-dateutil": {
"hashes": [ "hashes": [
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
@ -549,11 +617,11 @@
}, },
"scikit-rf": { "scikit-rf": {
"hashes": [ "hashes": [
"sha256:722def5442bb7033d608e8d3f717b38a3315846496925e85e8015cf006c36bb7", "sha256:796758dcd79650d8c66585583ac8ef13afde0d65d2da324ec60a4557eae52a9a",
"sha256:d7e1de31842d8922d1c741de7cc09aecf083a94ddc408ee2fe3f36a284858a09" "sha256:9864653abf0761049ba95deb37741581fff5cf8d43f4acf6e46576e34e04ad43"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==1.4.1" "version": "==1.5.0"
}, },
"scipy": { "scipy": {
"hashes": [ "hashes": [
@ -594,13 +662,23 @@
"markers": "python_version >= '3.10'", "markers": "python_version >= '3.10'",
"version": "==1.14.1" "version": "==1.14.1"
}, },
"shiboken6": {
"hashes": [
"sha256:1dc4c1976809b0e68872bb98474cccd590455bdcd015f0e0639907e94af27b6a",
"sha256:3ea127fd72be113b73cacd70e06687ad6f83c1c888047833c7dcdd5cf8e7f586",
"sha256:9a2f51d1ddd3b6d193a0f0fdc09f8d41f2092bc664723c9b9efc1056660d0608",
"sha256:ab5b60602ca6227103138aae89c4f5df3b1b8e249cbc8ec9e6e2a57f20ad9a91"
],
"markers": "python_version < '3.14' and python_version >= '3.9'",
"version": "==6.8.1"
},
"six": { "six": {
"hashes": [ "hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0" "version": "==1.17.0"
}, },
"typing-extensions": { "typing-extensions": {
"hashes": [ "hashes": [
@ -620,11 +698,11 @@
}, },
"xarray": { "xarray": {
"hashes": [ "hashes": [
"sha256:ae1d38cb44a0324dfb61e492394158ae22389bf7de9f3c174309c17376df63a0", "sha256:1ccace44573ddb862e210ad3ec204210654d2c750bec11bbe7d842dfc298591f",
"sha256:e369e2bac430e418c2448e5b96f07da4635f98c1319aa23cfeb3fbcb9a01d2e0" "sha256:6ee94f63ddcbdd0cf3909d1177f78cdac756640279c0e32ae36819a89cdaba37"
], ],
"markers": "python_version >= '3.10'", "markers": "python_version >= '3.10'",
"version": "==2024.10.0" "version": "==2024.11.0"
}, },
"zarr": { "zarr": {
"hashes": [ "hashes": [
@ -638,10 +716,48 @@
"develop": { "develop": {
"asttokens": { "asttokens": {
"hashes": [ "hashes": [
"sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7",
"sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0" "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"
], ],
"version": "==2.4.1" "markers": "python_version >= '3.8'",
"version": "==3.0.0"
},
"black": {
"hashes": [
"sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f",
"sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd",
"sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea",
"sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981",
"sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b",
"sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7",
"sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8",
"sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175",
"sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d",
"sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392",
"sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad",
"sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f",
"sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f",
"sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b",
"sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875",
"sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3",
"sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800",
"sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65",
"sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2",
"sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812",
"sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50",
"sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"
],
"index": "pypi",
"markers": "python_version >= '3.9'",
"version": "==24.10.0"
},
"click": {
"hashes": [
"sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
],
"markers": "python_version >= '3.7'",
"version": "==8.1.7"
}, },
"comm": { "comm": {
"hashes": [ "hashes": [
@ -653,12 +769,35 @@
}, },
"debugpy": { "debugpy": {
"hashes": [ "hashes": [
"sha256:a6531d952b565b7cb2fbd1ef5df3d333cf160b44f37547a4e7cf73666aca5d8d", "sha256:0e22f846f4211383e6a416d04b4c13ed174d24cc5d43f5fd52e7821d0ebc8920",
"sha256:e6355385db85cbd666be703a96ab7351bc9e6c61d694893206f8001e22aee091", "sha256:116bf8342062246ca749013df4f6ea106f23bc159305843491f64672a55af2e5",
"sha256:ec684553aba5b4066d4de510859922419febc710df7bba04fe9e7ef3de15d34f" "sha256:189058d03a40103a57144752652b3ab08ff02b7595d0ce1f651b9acc3a3a35a0",
"sha256:23dc34c5e03b0212fa3c49a874df2b8b1b8fda95160bd79c01eb3ab51ea8d851",
"sha256:28e45b3f827d3bf2592f3cf7ae63282e859f3259db44ed2b129093ca0ac7940b",
"sha256:2b26fefc4e31ff85593d68b9022e35e8925714a10ab4858fb1b577a8a48cb8cd",
"sha256:32db46ba45849daed7ccf3f2e26f7a386867b077f39b2a974bb5c4c2c3b0a280",
"sha256:40499a9979c55f72f4eb2fc38695419546b62594f8af194b879d2a18439c97a9",
"sha256:44b1b8e6253bceada11f714acf4309ffb98bfa9ac55e4fce14f9e5d4484287a1",
"sha256:52c3cf9ecda273a19cc092961ee34eb9ba8687d67ba34cc7b79a521c1c64c4c0",
"sha256:52d8a3166c9f2815bfae05f386114b0b2d274456980d41f320299a8d9a5615a7",
"sha256:61bc8b3b265e6949855300e84dc93d02d7a3a637f2aec6d382afd4ceb9120c9f",
"sha256:654130ca6ad5de73d978057eaf9e582244ff72d4574b3e106fb8d3d2a0d32458",
"sha256:6ad2688b69235c43b020e04fecccdf6a96c8943ca9c2fb340b8adc103c655e57",
"sha256:6c1f6a173d1140e557347419767d2b14ac1c9cd847e0b4c5444c7f3144697e4e",
"sha256:84e511a7545d11683d32cdb8f809ef63fc17ea2a00455cc62d0a4dbb4ed1c308",
"sha256:85de8474ad53ad546ff1c7c7c89230db215b9b8a02754d41cb5a76f70d0be296",
"sha256:8988f7163e4381b0da7696f37eec7aca19deb02e500245df68a7159739bbd0d3",
"sha256:8da1db4ca4f22583e834dcabdc7832e56fe16275253ee53ba66627b86e304da1",
"sha256:8ffc382e4afa4aee367bf413f55ed17bd91b191dcaf979890af239dda435f2a1",
"sha256:987bce16e86efa86f747d5151c54e91b3c1e36acc03ce1ddb50f9d09d16ded0e",
"sha256:ad7efe588c8f5cf940f40c3de0cd683cc5b76819446abaa50dc0829a30c094db",
"sha256:bb3b15e25891f38da3ca0740271e63ab9db61f41d4d8541745cfc1824252cb28",
"sha256:c928bbf47f65288574b78518449edaa46c82572d340e2750889bbf8cd92f3737",
"sha256:ce291a5aca4985d82875d6779f61375e959208cdf09fcec40001e65fb0a54768",
"sha256:d8768edcbeb34da9e11bcb8b5c2e0958d25218df7a6e56adf415ef262cd7b6d1"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==1.8.8" "version": "==1.8.11"
}, },
"decorator": { "decorator": {
"hashes": [ "hashes": [
@ -684,6 +823,15 @@
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==2.1.0" "version": "==2.1.0"
}, },
"flake8": {
"hashes": [
"sha256:049d058491e228e03e67b390f311bbf88fce2dbaa8fa673e7aea87b7198b8d38",
"sha256:597477df7860daa5aa0fdd84bf5208a043ab96b8e96ab708770ae0364dd03213"
],
"index": "pypi",
"markers": "python_full_version >= '3.8.1'",
"version": "==7.1.1"
},
"ipykernel": { "ipykernel": {
"hashes": [ "hashes": [
"sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5", "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5",
@ -695,11 +843,11 @@
}, },
"ipython": { "ipython": {
"hashes": [ "hashes": [
"sha256:0188a1bd83267192123ccea7f4a8ed0a78910535dbaa3f37671dca76ebd429c8", "sha256:85ec56a7e20f6c38fce7727dcca699ae4ffc85985aa7b23635a8008f918ae321",
"sha256:40b60e15b22591450eef73e40a027cf77bd652e757523eebc5bd7c7c498290eb" "sha256:cb0a405a306d2995a5cbb9901894d240784a9f341394c6ba3f4fe8c6eb89ff6e"
], ],
"markers": "python_version >= '3.10'", "markers": "python_version >= '3.10'",
"version": "==8.29.0" "version": "==8.30.0"
}, },
"ipywidgets": { "ipywidgets": {
"hashes": [ "hashes": [
@ -710,13 +858,22 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==8.1.5" "version": "==8.1.5"
}, },
"isort": {
"hashes": [
"sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109",
"sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"
],
"index": "pypi",
"markers": "python_full_version >= '3.8.0'",
"version": "==5.13.2"
},
"jedi": { "jedi": {
"hashes": [ "hashes": [
"sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd", "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0",
"sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0" "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==0.19.1" "version": "==0.19.2"
}, },
"jupyter-client": { "jupyter-client": {
"hashes": [ "hashes": [
@ -750,6 +907,22 @@
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==0.1.7" "version": "==0.1.7"
}, },
"mccabe": {
"hashes": [
"sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325",
"sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"
],
"markers": "python_version >= '3.6'",
"version": "==0.7.0"
},
"mypy-extensions": {
"hashes": [
"sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
"sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
],
"markers": "python_version >= '3.5'",
"version": "==1.0.0"
},
"nest-asyncio": { "nest-asyncio": {
"hashes": [ "hashes": [
"sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe",
@ -774,6 +947,14 @@
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==0.8.4" "version": "==0.8.4"
}, },
"pathspec": {
"hashes": [
"sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08",
"sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"
],
"markers": "python_version >= '3.8'",
"version": "==0.12.1"
},
"pexpect": { "pexpect": {
"hashes": [ "hashes": [
"sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523",
@ -835,6 +1016,22 @@
], ],
"version": "==0.2.3" "version": "==0.2.3"
}, },
"pycodestyle": {
"hashes": [
"sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3",
"sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"
],
"markers": "python_version >= '3.8'",
"version": "==2.12.1"
},
"pyflakes": {
"hashes": [
"sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f",
"sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"
],
"markers": "python_version >= '3.8'",
"version": "==3.2.0"
},
"pygments": { "pygments": {
"hashes": [ "hashes": [
"sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
@ -968,11 +1165,11 @@
}, },
"six": { "six": {
"hashes": [ "hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0" "version": "==1.17.0"
}, },
"stack-data": { "stack-data": {
"hashes": [ "hashes": [
@ -981,22 +1178,60 @@
], ],
"version": "==0.6.3" "version": "==0.6.3"
}, },
"tomli": {
"hashes": [
"sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6",
"sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd",
"sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c",
"sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b",
"sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8",
"sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6",
"sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77",
"sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff",
"sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea",
"sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192",
"sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249",
"sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee",
"sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4",
"sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98",
"sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8",
"sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4",
"sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281",
"sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744",
"sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69",
"sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13",
"sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140",
"sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e",
"sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e",
"sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc",
"sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff",
"sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec",
"sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2",
"sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222",
"sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106",
"sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272",
"sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a",
"sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"
],
"markers": "python_version < '3.11'",
"version": "==2.2.1"
},
"tornado": { "tornado": {
"hashes": [ "hashes": [
"sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8", "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803",
"sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f", "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec",
"sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4", "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482",
"sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3", "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634",
"sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14", "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38",
"sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842", "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b",
"sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9", "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c",
"sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698", "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf",
"sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7", "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946",
"sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d", "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73",
"sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4" "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1"
], ],
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==6.4.1" "version": "==6.4.2"
}, },
"traitlets": { "traitlets": {
"hashes": [ "hashes": [

View File

@ -1,6 +1,6 @@
# Charon # Charon VNA
Named after [Pluto's moon](https://en.wikipedia.org/wiki/Charon_(moon)), Charon uses the [ADI Pluto SDR]() as a vector network analyzer. The basic usage is as a 1 port VNA but this can be extended to arbitrarily many ports with the addition of a couple RF switches. Named after [Pluto's moon](https://en.wikipedia.org/wiki/Charon_(moon)), Charon uses the [ADI Pluto SDR](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/adalm-pluto.html) as a vector network analyzer. The basic usage is as a 1 port VNA but this can be extended to arbitrarily many ports with the addition of a couple RF switches.
## Installation ## Installation
@ -9,6 +9,26 @@ On Ubuntu 22.04 just run `sudo apt-get install -y libiio-dev`
2. `pip install charon-vna` 2. `pip install charon-vna`
## Hardware Setup
You need a few things:
- [Analog Devices Pluto SDR](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/adalm-pluto.html).
Any variant of the Pluto *should* work too such as the [Pluto+](https://github.com/plutoplus/plutoplus?tab=readme-ov-file) however I have only tested with the basic flavor.
- Directional couplers (1 per port up to 4 ports).
I have been using [AAMCS-UDC-0.5G-18G-10dB-Sf](http://www.aa-mcs.com/wp-content/uploads/documents/AAMCS-UDC-0.5G-18G-10dB-Sf.pdf)
- Charon switch board - coming soon.
Without this, you'll be limited to S11 and uncalibrated S21 measurements (with required re-cabling).
There's nothing special about this particular board, if you want more than 4 ports you can make your own pretty easily. You just need 3 SPxT switches. Note that these switches will see tons of cycles so avoid mechanical switches.
- SMA cables
### Pluto Configuration
Most of my testing is with Pluto firmware [v0.39](https://github.com/analogdevicesinc/plutosdr-fw/releases/tag/v0.39) though this may work with other firmware versions. Instructions for upgrading firmware are on the [Analog Devices wiki](https://wiki.analog.com/university/tools/pluto/users/firmware).
We need two receive channels on the SDR. If you have a Pluto+ that should already be configured and you can skip this step.
Analog devices has a [guide](https://wiki.analog.com/university/tools/pluto/users/customizing#updating_to_the_ad9364) for enabling the second channel. Ideally this should be set as `ad9361` to enable a wider band of operation in addition to the second channel, however the critical setting is enabling 2r2t.
## Usage ## Usage
There will be some sort of GUI because that sounds useful. There will be some sort of GUI because that sounds useful.
@ -26,21 +46,3 @@ Absolute output power is generally not well calibrated for VNAs anyway and has n
If you have an RF power meter you can generate your own power calibration. If you have an RF power meter you can generate your own power calibration.
Note that unlike the main calibration, power calibration frequencies do not need to match the measurement frequencies. Values are interpolated. Note that unlike the main calibration, power calibration frequencies do not need to match the measurement frequencies. Values are interpolated.
## Hardware
You need a few things:
- [Analog Devices Pluto SDR](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/adalm-pluto.html).
Any variant of the Pluto *should* work too such as the [Pluto+](https://github.com/plutoplus/plutoplus?tab=readme-ov-file)
- Directional couplers (1 per port up to 4 ports).
I have been using [AAMCS-UDC-0.5G-18G-10dB-Sf](http://www.aa-mcs.com/wp-content/uploads/documents/AAMCS-UDC-0.5G-18G-10dB-Sf.pdf)
- Charon switch board - coming soon.
Without this, you'll be limited to S11 and uncalibrated S21 measurements (with required re-cabling).
There's nothing special about this particular board, if you want more than 4 ports you can make your own pretty easily. You just need 3 SPxT switches. Note that these switches will see tons of cycles so avoid mechanical switches.
- SMA cables
### Pluto Modification
We need two receive channels on the SDR. If you have a Pluto+ that should already be configured and you can skip this step.
Analog devices has a [guide](https://wiki.analog.com/university/tools/pluto/users/customizing#updating_to_the_ad9364) for enabling the second channel. Ideally this should be set as `ad9361` to enable a wider band of operation in addition to the second channel, however the critical setting is enabling 2r2t.

26
charon_vna/cli.py Normal file
View File

@ -0,0 +1,26 @@
# %% imports
from pathlib import Path
import click
# from charon_vna.vna import Charon
@click.command()
@click.argument("start", type=float)
@click.argument("stop", type=float)
@click.argument("pts", type=int)
@click.option("--ports", "-n", type=int, default=1, help="Number of ports.")
@click.option("--power", "-p", type=float, default=-5, help="Port output power [dBm].")
@click.option("--snp", "-o", type=click.Path(), help="Path for output Touchstone file.")
def capture(start: float, stop: float, pts: int, power: float, snp: Path, ports: int):
raise NotImplementedError
# %%
def main():
capture()
if __name__ == "__main__":
main()

323
charon_vna/gui.py Normal file
View File

@ -0,0 +1,323 @@
# %% imports
import sys
from pathlib import Path
from typing import Callable, List, Literal, Tuple
import matplotlib as mpl
import numpy as np
import xarray as xr
from matplotlib import pyplot as plt
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from matplotlib.lines import Line2D
from matplotlib.ticker import EngFormatter
from numpy import typing as npt
from PySide6.QtGui import QAction, QKeySequence
from PySide6.QtWidgets import (
QApplication,
QFileDialog,
QInputDialog,
QMainWindow,
QMenu,
QProgressBar,
QVBoxLayout,
QWidget,
)
from skrf import plotting as rf_plt
from vna import Charon
from charon_vna.util import db20, s2vswr
# %%
DEFAULT_CONFIG = dict(
frequency=np.arange(1e9, 2e9, 11), # Hz
power=-5, # dB
)
CONFIG_SUFFIX = ".json"
class PlotWidget(QWidget):
traces: List[Tuple[int | str]]
lines: List[Line2D]
def __init__(self, type_: str = "logmag"):
super().__init__()
self.traces = [(1, 1)]
layout = QVBoxLayout()
self.setLayout(layout)
self.fig = plt.Figure(figsize=(5, 4), dpi=100, tight_layout=True)
self.ax = self.fig.add_subplot(111)
self.set_plot_type(type_)
self.lines = [
self.ax.plot([np.nan], [np.nan], label="$S_{" + str(m) + str(n) + "}$")[0] for m, n in self.traces
]
self.ax.legend(loc="upper right")
canvas = FigureCanvasQTAgg(self.fig)
layout.addWidget(canvas)
# toolbar = QToolBar("Toolbar")
# toolbar.addAction("blah")
# self.addToolBar(toolbar)
def set_plot_type(
self,
type_: Literal["logmag", "phase", "vswr", "smith"],
sweep_type: Literal["frequency", "time"] = "frequency",
) -> None:
if sweep_type != "frequency":
raise NotImplementedError("Only frequency sweeps are currently supported")
if type_ == "logmag":
self.setup_logmag()
elif type_ == "phase":
self.setup_phase()
elif type_ == "vswr":
self.setup_vswr()
elif type_ == "smith":
self.setup_smith()
else:
raise ValueError(f"Unknown plot type: {type_}")
self._plot_type = type_
def update_plot(self, data: xr.DataArray):
if self._plot_type == "logmag":
self.update_logmag(data)
elif self._plot_type == "phase":
self.update_phase(data)
elif self._plot_type == "vswr":
self.update_vswr(data)
elif self._plot_type == "smith":
self.update_smith(data)
def setup_rect(self) -> None:
self.ax.grid(True)
self.ax.xaxis.set_major_formatter(EngFormatter())
self.ax.set_xlabel("Frequency [Hz]")
def update_rect(self, data: xr.DataArray, func: Callable[[npt.ArrayLike], npt.ArrayLike]) -> None:
self.ax.set_xlim(data["frequency"].min().data, data["frequency"].max().data)
for ii, (m, n) in enumerate(self.traces):
self.lines[ii].set_xdata(data["frequency"])
self.lines[ii].set_ydata(func(data.sel(m=m, n=n)))
self.fig.canvas.draw()
def setup_logmag(self, ylim: List[float] = [-30, 30]) -> None:
self.setup_rect()
self.ax.set_ylim(ylim)
self.ax.set_ylabel("Amplitude [dB]")
def update_logmag(self, data: xr.DataArray) -> None:
self.update_rect(data, db20)
def setup_phase(self) -> None:
self.setup_rect()
self.ax.set_ylim(-200, 200)
self.ax.set_ylabel("Phase [deg]")
def update_phase(self, data: xr.DataArray):
self.update_rect(data, lambda s: np.angle(s, deg=True))
def setup_vswr(self) -> None:
self.setup_rect()
self.ax.set_yticks(np.arange(1, 11))
self.ax.set_ylim(1, 10)
self.ax.set_ylabel("VSWR")
def update_vswr(self, data: xr.DataArray) -> None:
self.update_rect(data, s2vswr)
def setup_smith(self) -> None:
self.ax.grid(False)
self.ax.set_xlim(-1, 1)
self.ax.set_ylim(-1, 1)
self.ax.set_aspect("equal")
rf_plt.smith(ax=self.ax, smithR=1, chart_type="z", draw_vswr=None)
def update_smith(self, data: xr.DataArray) -> None:
for ii, (m, n) in enumerate(self.traces):
sel = data.sel(m=m, n=n)
self.lines[ii].set_xdata(sel.real)
self.lines[ii].set_ydata(sel.imag)
self.fig.canvas.draw()
# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):
config_path: Path | None
# device: Charon
plots: List[PlotWidget]
def __init__(self):
super().__init__()
self.config_path = None
self._frequency = np.linspace(1e9, 2e9, 101) # TODO: read frequency from config
self.vna = Charon("ip:192.168.3.1", frequency=DEFAULT_CONFIG["frequency"])
mpl.use("QtAgg")
self.setWindowTitle("Charon VNA")
# Menu
menubar = self.menuBar()
menu_file = QMenu("&File")
menubar.addMenu(menu_file)
action_open_config = QAction("&Open Configuration", self)
menu_file.addAction(action_open_config)
action_open_config.triggered.connect(self.open_config)
action_open_config.setShortcut(QKeySequence("Ctrl+O"))
action_save_config = QAction("&Save Configuration", self)
menu_file.addAction(action_save_config)
action_save_config.triggered.connect(self.save_config)
action_save_config.setShortcut(QKeySequence("Ctrl+S"))
action_saveas_config = QAction("Save Configuration &As", self)
menu_file.addAction(action_saveas_config)
action_saveas_config.triggered.connect(self.saveas_config)
action_saveas_config.setShortcut(QKeySequence("Ctrl+Shift+S"))
menu_stimulus = QMenu("&Stimulus")
menubar.addMenu(menu_stimulus)
action_set_frequency = QAction("&Frequency", self)
menu_stimulus.addAction(action_set_frequency)
action_set_frequency.triggered.connect(self.set_frequency)
action_set_power = QAction("&Power", self)
menu_stimulus.addAction(action_set_power)
# action_set_power.triggered.connect(self.set_power)
action_trigger = QAction("&Trigger", self)
action_trigger.triggered.connect(self.capture)
action_trigger.setShortcut("Ctrl+T")
menu_stimulus.addAction(action_trigger)
menu_calibration = QMenu("&Calibration")
menubar.addMenu(menu_calibration)
# Content
window_layout = QVBoxLayout()
prog_sweep = QProgressBar()
prog_sweep.setMinimum(0)
prog_sweep.setMaximum(100)
prog_sweep.setFormat("%v / %m")
# prog_sweep.setTextVisible(False)
prog_sweep.setValue(50)
window_layout.addWidget(prog_sweep)
self.prog_sweep = prog_sweep
# window_widget.se
plot_layout = QVBoxLayout()
# TODO: handle plots properly
self.plots = []
for type_ in ["logmag", "phase", "vswr", "smith"]:
self.plots.append(PlotWidget(type_=type_))
plot_layout.addWidget(self.plots[-1])
plot_widget = QWidget()
plot_widget.setLayout(plot_layout)
window_layout.addWidget(plot_widget)
# Set the central widget of the Window.
widget = QWidget()
widget.setLayout(window_layout)
self.setCentralWidget(widget)
def saveas_config(self) -> None:
print("Prompting for save path...")
dialog = QFileDialog(self)
dialog.setDefaultSuffix(CONFIG_SUFFIX)
dialog.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)
if dialog.exec():
config_path = Path(dialog.selectedFiles()[0])
print(config_path)
if config_path.suffix != CONFIG_SUFFIX:
raise ValueError(
f"{config_path.name} is not a valid configuration file. Must have extension {CONFIG_SUFFIX}"
)
self.config_path = config_path
print(f"Config path is now {self.config_path.resolve()}")
self.save_config()
def open_config(self) -> None:
print("Prompting for load path...")
dialog = QFileDialog(self)
dialog.setNameFilter(f"*{CONFIG_SUFFIX}")
dialog.setAcceptMode(QFileDialog.AcceptMode.AcceptOpen)
if dialog.exec():
config_path = Path(dialog.selectedFiles()[0])
print(config_path)
if config_path.suffix != CONFIG_SUFFIX:
raise ValueError(
f"{config_path.name} is not a valid configuration file. Must have extension {CONFIG_SUFFIX}"
)
self.config_path = config_path
print(f"Config path is now {self.config_path.resolve()}")
self.load_config(self.config_path)
def save_config(self) -> None:
if self.config_path is None:
self.saveas_config()
else:
print(f"Saving config to {self.config_path.resolve()}")
# TODO: save config
def load_config(self, path: Path) -> None:
print(f"Loading config from {path}...")
# TODO: load config
def capture(self) -> None:
def callback(done: int, total: int):
self.prog_sweep.setMaximum(total)
self.prog_sweep.setValue(done)
s = self.vna.vna_capture(self._frequency, callback)
data = xr.DataArray(
[[s]],
dims=["m", "n", "frequency"],
coords=dict(
frequency=s.coords["frequency"],
m=[1],
n=[1],
),
)
for plot in self.plots:
plot.update_plot(data)
def set_frequency(self, *, frequency: npt.ArrayLike | None = None):
print(frequency)
if frequency is None:
start, ok = QInputDialog.getDouble(
self, "Start Frequency", "Start Frequency", minValue=30e6, maxValue=6e9, value=1e9
)
stop, ok = QInputDialog.getDouble(
self, "Stop Frequency", "Stop Frequency", minValue=30e6, maxValue=6e9, value=2e9
)
points, ok = QInputDialog.getInt(self, "Points", "Points", minValue=2, value=101)
frequency = np.linspace(start, stop, points)
# Currently does not support zero span
self._frequency = frequency
def main() -> None:
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
# %%
if __name__ == "__main__":
main()

90
charon_vna/gui_helpers.py Normal file
View File

@ -0,0 +1,90 @@
from PySide6.QtCore import QMargins, QPoint, QRect, QSize, Qt
from PySide6.QtWidgets import QLayout, QSizePolicy
class FlowLayout(QLayout):
def __init__(self, parent=None):
super().__init__(parent)
if parent is not None:
self.setContentsMargins(QMargins(0, 0, 0, 0))
self._item_list = []
def __del__(self):
item = self.takeAt(0)
while item:
item = self.takeAt(0)
def addItem(self, item):
self._item_list.append(item)
def count(self):
return len(self._item_list)
def itemAt(self, index):
if 0 <= index < len(self._item_list):
return self._item_list[index]
return None
def takeAt(self, index):
if 0 <= index < len(self._item_list):
return self._item_list.pop(index)
return None
def expandingDirections(self):
return Qt.Orientation(0)
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
height = self._do_layout(QRect(0, 0, width, 0), True)
return height
def setGeometry(self, rect):
super(FlowLayout, self).setGeometry(rect)
self._do_layout(rect, False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QSize()
for item in self._item_list:
size = size.expandedTo(item.minimumSize())
size += QSize(2 * self.contentsMargins().top(), 2 * self.contentsMargins().top())
return size
def _do_layout(self, rect, test_only):
x = rect.x()
y = rect.y()
line_height = 0
spacing = self.spacing()
for item in self._item_list:
style = item.widget().style()
layout_spacing_x = style.layoutSpacing(
QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Orientation.Horizontal
)
layout_spacing_y = style.layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)
space_x = spacing + layout_spacing_x
space_y = spacing + layout_spacing_y
next_x = x + item.sizeHint().width() + space_x
if next_x - space_x > rect.right() and line_height > 0:
x = rect.x()
y = y + line_height + space_y
next_x = x + item.sizeHint().width() + space_x
line_height = 0
if not test_only:
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
x = next_x
line_height = max(line_height, item.sizeHint().height())
return y + line_height - rect.y()

View File

@ -1,7 +1,6 @@
from pathlib import Path from pathlib import Path
import skrf as rf import skrf as rf
import xarray as xr
from util import net2s from util import net2s

View File

@ -1,6 +1,7 @@
import numpy as np import numpy as np
import skrf as rf import skrf as rf
import xarray as xr import xarray as xr
from numpy import typing as npt
HAM_BANDS = [ HAM_BANDS = [
[135.7e3, 137.8e3], [135.7e3, 137.8e3],
@ -37,12 +38,16 @@ HAM_BANDS = [
] ]
def db10(p): def db10(p: npt.ArrayLike) -> npt.ArrayLike:
return 10 * np.log10(np.abs(p)) return 10 * np.log10(np.abs(p))
def db20(p): def db20(v: npt.ArrayLike) -> npt.ArrayLike:
return 20 * np.log10(np.abs(p)) return 20 * np.log10(np.abs(v))
def s2vswr(s: npt.ArrayLike) -> npt.ArrayLike:
return (1 + np.abs(s)) / (1 - np.abs(s))
def minmax(x): def minmax(x):

View File

@ -1,10 +1,11 @@
# %% imports # %% imports
import copy import copy
from pathlib import Path from pathlib import Path
from typing import Any, Dict, Tuple from typing import Any, Callable, Dict, Tuple
import adi import adi
import iio
# import iio
import numpy as np import numpy as np
import skrf as rf import skrf as rf
import xarray as xr import xarray as xr
@ -37,7 +38,7 @@ class Charon:
def __init__( def __init__(
self, self,
uri: str, uri: str = "192.168.2.1",
frequency: npt.ArrayLike = np.linspace(1e9, 2e9, 3), frequency: npt.ArrayLike = np.linspace(1e9, 2e9, 3),
ports: Tuple[int] = (1,), ports: Tuple[int] = (1,),
): ):
@ -81,7 +82,7 @@ class Charon:
# self.ctrl = ctx.find_device("ad9361-phy") # self.ctrl = ctx.find_device("ad9361-phy")
# # raw ad9361 register accesss: # # raw ad9361 register accesss:
# # https://ez.analog.com/linux-software-drivers/f/q-a/120853/control-fmcomms3-s-gpo-with-python # # https://ez.analog.com/linux-software-drivers/f/q-a/120853/control-fmcomms3-s-gpo-with-python
# # https://www.analog.com/media/cn/technical-documentation/user-guides/ad9364_register_map_reference_manual_ug-672.pdf # # https://www.analog.com/media/cn/technical-documentation/user-guides/ad9364_register_map_reference_manual_ug-672.pdf # noqa: E501
# self.ctrl.reg_write(0x26, 0x90) # bit 7: AuxDAC Manual, bit 4: GPO Manual # self.ctrl.reg_write(0x26, 0x90) # bit 7: AuxDAC Manual, bit 4: GPO Manual
# self._set_gpo(self.ports[0] - 1) # self._set_gpo(self.ports[0] - 1)
# # TODO: init AuxDAC # # TODO: init AuxDAC
@ -140,8 +141,9 @@ class Charon:
self.set_output_power(power) self.set_output_power(power)
self.sdr.tx_lo = int(frequency - self.FREQUENCY_OFFSET) self.sdr.tx_lo = int(frequency - self.FREQUENCY_OFFSET)
self.sdr.tx_cyclic_buffer = True self.sdr.tx_cyclic_buffer = True
# self.sdr.tx(generate_tone(f=self.FREQUENCY_OFFSET, fs=self.sdr.sample_rate)) # For some reason the pluto's DDS has truly horrendous phase noise to the point where it looks modulated
self.sdr.dds_single_tone(self.FREQUENCY_OFFSET, scale=0.9, channel=0) self.sdr.tx(generate_tone(f=self.FREQUENCY_OFFSET, fs=self.sdr.sample_rate))
# self.sdr.dds_single_tone(self.FREQUENCY_OFFSET, scale=0.9, channel=0)
def _rx(self, count: int = 1, fc: float | None = None) -> npt.ArrayLike: def _rx(self, count: int = 1, fc: float | None = None) -> npt.ArrayLike:
if count < 1: if count < 1:
@ -205,7 +207,7 @@ class Charon:
s.loc[dict(frequency=frequency)] = self.get_b_over_a(frequency=frequency) s.loc[dict(frequency=frequency)] = self.get_b_over_a(frequency=frequency)
return s return s
def vna_capture(self, frequency: npt.ArrayLike): def vna_capture(self, frequency: npt.ArrayLike, callback: Callable[int, int] | None):
s = xr.DataArray( s = xr.DataArray(
np.empty(len(frequency), dtype=np.complex128), np.empty(len(frequency), dtype=np.complex128),
dims=["frequency"], dims=["frequency"],
@ -213,7 +215,9 @@ class Charon:
frequency=frequency, frequency=frequency,
), ),
) )
for freq in s.frequency.data: for ff, freq in enumerate(s.frequency.data):
if callback is not None:
callback(ff, len(s.frequency))
self.set_output(frequency=freq, power=-5) self.set_output(frequency=freq, power=-5)
self.sdr.rx_destroy_buffer() self.sdr.rx_destroy_buffer()
self.sdr.rx_lo = int(freq) self.sdr.rx_lo = int(freq)
@ -224,163 +228,166 @@ class Charon:
self.sdr.rx_hardwaregain_chan1 = 40 self.sdr.rx_hardwaregain_chan1 = 40
rx = self.sdr.rx() rx = self.sdr.rx()
s.loc[dict(frequency=freq)] = np.mean(rx[1] / rx[0]) s.loc[dict(frequency=freq)] = np.mean(rx[1] / rx[0])
if callback is not None:
callback(len(s.frequency), len(s.frequency))
return s return s
# %% # %%
sdr = Charon("ip:192.168.3.1", frequency=np.linspace(1e9, 1.1e9, 11)) if __name__ == "__main__":
pass
# %% initialization # %%
config = sdr.get_config() sdr = Charon("ip:192.168.3.1", frequency=np.linspace(1e9, 1.1e9, 11))
# print(sdr.ctrl.debug_attrs["adi,rx-rf-port-input-select"].value)
# print(sdr.ctrl.debug_attrs["adi,tx-rf-port-input-select"].value)
config
# %% generate tone # %% initialization
fc = 1e9 config = sdr.get_config()
sdr.set_output(frequency=fc + sdr.FREQUENCY_OFFSET, power=-5) # print(sdr.ctrl.debug_attrs["adi,rx-rf-port-input-select"].value)
# print(sdr.ctrl.debug_attrs["adi,tx-rf-port-input-select"].value)
config
# %% capture data # %% generate tone
data = sdr._rx(1, fc=fc) fc = 1e9
sdr.set_output(frequency=fc + sdr.FREQUENCY_OFFSET, power=-5)
# %% Plot in time # %% capture data
fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True) data = sdr._rx(1, fc=fc)
axs[0].plot(np.real(data).T)
axs[1].plot(np.imag(data).T)
axs[0].set_ylabel("Real")
axs[1].set_ylabel("Imag")
axs[0].grid(True)
axs[1].grid(True)
axs[-1].set_xlabel("Sample")
axs[-1].set_xlim(0, data.shape[-1])
fig.show()
# %% # %% Plot in time
fig, ax = plt.subplots(1, 1, tight_layout=True) fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True)
ax.plot(np.real(data).T, np.imag(data).T) axs[0].plot(np.real(data).T)
ax.grid(True) axs[1].plot(np.imag(data).T)
ax.set_aspect("equal") axs[0].set_ylabel("Real")
ax.set_xlabel("Real") axs[1].set_ylabel("Imag")
ax.set_ylabel("Imag") axs[0].grid(True)
ax.set_xlim(np.array([-1, 1]) * (2 ** (12 - 1) - 1)) axs[1].grid(True)
ax.set_ylim(ax.get_xlim()) axs[-1].set_xlabel("Sample")
fig.show() axs[-1].set_xlim(0, data.shape[-1])
fig.show()
# %% Plot in frequency # %%
f = np.fft.fftfreq(data.shape[-1], 1 / sdr.sdr.sample_rate) fig, ax = plt.subplots(1, 1, tight_layout=True)
RX_BITS = 12 # for each of i, q (including sign bit) ax.plot(np.real(data).T, np.imag(data).T)
fft_data = np.fft.fft(data, axis=-1, norm="forward") / (2 ** (RX_BITS - 1)) ax.grid(True)
plt.figure() ax.set_aspect("equal")
for cc, chan in enumerate(sdr.sdr.rx_enabled_channels): ax.set_xlabel("Real")
plt.plot( ax.set_ylabel("Imag")
np.fft.fftshift(f), ax.set_xlim(np.array([-1, 1]) * (2 ** (12 - 1) - 1))
db20(np.fft.fftshift(fft_data[cc])), ax.set_ylim(ax.get_xlim())
label=f"Channel {chan}", fig.show()
# %% Plot in frequency
f = np.fft.fftfreq(data.shape[-1], 1 / sdr.sdr.sample_rate)
RX_BITS = 12 # for each of i, q (including sign bit)
fft_data = np.fft.fft(data, axis=-1, norm="forward") / (2 ** (RX_BITS - 1))
plt.figure()
for cc, chan in enumerate(sdr.sdr.rx_enabled_channels):
plt.plot(
np.fft.fftshift(f),
db20(np.fft.fftshift(fft_data[cc])),
label=f"Channel {chan}",
)
plt.legend()
plt.ylim(-100, 0)
plt.xlabel("Frequency [Hz]")
plt.ylabel("Power [dBfs]")
plt.title(f"Fc = {sdr.sdr.rx_lo / 1e9} GHz")
plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True)
plt.show()
# %%
s = sdr.vna_capture(frequency=np.linspace(70e6, 200e6, 101))
# %% Plot Logmag
fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True)
axs[0].plot(s.frequency, db20(s), label="Measured")
axs[1].plot(s.frequency, np.rad2deg(np.angle((s))), label="Measured")
axs[0].grid(True)
axs[1].grid(True)
axs[0].set_ylim(-80, 0)
axs[1].set_ylim(-200, 200)
axs[1].set_xlim(np.min(s.frequency), np.max(s.frequency))
axs[1].xaxis.set_major_formatter(EngFormatter(places=1))
axs[1].set_xlabel("Frequency")
axs[0].set_ylabel("|S11| [dB]")
axs[1].set_ylabel("∠S11 [deg]")
reference_sparams = None
reference_sparams = dir_ / "RBP-135+_Plus25degC.s2p"
if reference_sparams is not None:
ref = rf.Network(reference_sparams)
rbp135 = net2s(ref)
axs[0].plot(rbp135.frequency, db20(rbp135.sel(m=1, n=1)), label="Datasheet")
axs[1].plot(rbp135.frequency, np.rad2deg(np.angle(rbp135.sel(m=2, n=1))), label="Datasheet")
axs[0].legend()
axs[1].legend()
plt.show()
# %% SOL calibration
cal_frequency = np.linspace(70e6, 600e6, 101)
ideal_cal_frequency = rf.Frequency(np.min(cal_frequency), np.max(cal_frequency), len(cal_frequency))
input("Connect SHORT and press ENTER...")
short = sdr.vna_capture(frequency=cal_frequency)
input("Connect OPEN and press ENTER...")
open = sdr.vna_capture(frequency=cal_frequency)
input("Connect LOAD and press ENTER...")
load = sdr.vna_capture(frequency=cal_frequency)
short_net = s2net(short)
open_net = s2net(open)
load_net = s2net(load)
cal_ideal = rf.media.DefinedGammaZ0(frequency=ideal_cal_frequency)
calibration = rf.calibration.OnePort(
[short_net, open_net, load_net],
[cal_ideal.short(), cal_ideal.open(), cal_ideal.load(0)],
) )
plt.legend()
plt.ylim(-100, 0)
plt.xlabel("Frequency [Hz]")
plt.ylabel("Power [dBfs]")
plt.title(f"Fc = {sdr.sdr.rx_lo / 1e9} GHz")
plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True)
plt.show()
# %%
s = sdr.vna_capture(frequency=cal_frequency)
# %% # %%
s = sdr.vna_capture(frequency=np.linspace(70e6, 200e6, 101)) s_calibrated = calibration.apply_cal(s2net(s))
# %% Plot Logmag plt.figure()
fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True) s_calibrated.plot_s_smith()
# ref.plot_s_smith(m=1, n=1)
plt.show()
axs[0].plot(s.frequency, db20(s), label="Measured") plt.figure()
axs[1].plot(s.frequency, np.rad2deg(np.angle((s))), label="Measured") for start, stop in HAM_BANDS:
plt.axvspan(start, stop, alpha=0.1, color="k")
s_calibrated.plot_s_db()
# ref.plot_s_db(m=1, n=1)
plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True)
plt.xlim(s_calibrated.f[0], s_calibrated.f[-1])
plt.show()
axs[0].grid(True) plt.figure()
axs[1].grid(True) for start, stop in HAM_BANDS:
plt.axvspan(start, stop, alpha=0.1, color="k")
# s_calibrated.plot_s_vswr()
# drop invalid points
vswr = copy.deepcopy(s_calibrated.s_vswr[:, 0, 0])
vswr[vswr < 1] = np.nan
plt.plot(s_calibrated.f, vswr)
plt.axhline(1, color="k", linestyle="--")
plt.ylabel("VSWR")
plt.xlabel("Frequency [Hz]")
# ref.plot_s_vswr(m=1, n=1)
plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True)
plt.ylim(0, 10)
plt.xlim(s_calibrated.f[0], s_calibrated.f[-1])
plt.show()
axs[0].set_ylim(-80, 0) # %%
axs[1].set_ylim(-200, 200)
axs[1].set_xlim(np.min(s.frequency), np.max(s.frequency))
axs[1].xaxis.set_major_formatter(EngFormatter(places=1))
axs[1].set_xlabel("Frequency")
axs[0].set_ylabel("|S11| [dB]")
axs[1].set_ylabel("∠S11 [deg]")
reference_sparams = None
reference_sparams = dir_ / "RBP-135+_Plus25degC.s2p"
if reference_sparams is not None:
ref = rf.Network(reference_sparams)
rbp135 = net2s(ref)
axs[0].plot(rbp135.frequency, db20(rbp135.sel(m=1, n=1)), label="Datasheet")
axs[1].plot(rbp135.frequency, np.rad2deg(np.angle(rbp135.sel(m=2, n=1))), label="Datasheet")
axs[0].legend()
axs[1].legend()
plt.show()
# %% SOL calibration
cal_frequency = np.linspace(70e6, 600e6, 101)
ideal_cal_frequency = rf.Frequency(np.min(cal_frequency), np.max(cal_frequency), len(cal_frequency))
input("Connect SHORT and press ENTER...")
short = sdr.vna_capture(frequency=cal_frequency)
input("Connect OPEN and press ENTER...")
open = sdr.vna_capture(frequency=cal_frequency)
input("Connect LOAD and press ENTER...")
load = sdr.vna_capture(frequency=cal_frequency)
short_net = s2net(short)
open_net = s2net(open)
load_net = s2net(load)
cal_ideal = rf.media.DefinedGammaZ0(frequency=ideal_cal_frequency)
calibration = rf.calibration.OnePort(
[short_net, open_net, load_net],
[cal_ideal.short(), cal_ideal.open(), cal_ideal.load(0)],
)
# %%
s = sdr.vna_capture(frequency=cal_frequency)
# %%
s_calibrated = calibration.apply_cal(s2net(s))
plt.figure()
s_calibrated.plot_s_smith()
# ref.plot_s_smith(m=1, n=1)
plt.show()
plt.figure()
for start, stop in HAM_BANDS:
plt.axvspan(start, stop, alpha=0.1, color="k")
s_calibrated.plot_s_db()
# ref.plot_s_db(m=1, n=1)
plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True)
plt.xlim(s_calibrated.f[0], s_calibrated.f[-1])
plt.show()
plt.figure()
for start, stop in HAM_BANDS:
plt.axvspan(start, stop, alpha=0.1, color="k")
# s_calibrated.plot_s_vswr()
# drop invalid points
vswr = copy.deepcopy(s_calibrated.s_vswr[:, 0, 0])
vswr[vswr < 1] = np.nan
plt.plot(s_calibrated.f, vswr)
plt.axhline(1, color="k", linestyle="--")
plt.ylabel("VSWR")
plt.xlabel("Frequency [Hz]")
# ref.plot_s_vswr(m=1, n=1)
plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True)
plt.ylim(0, 10)
plt.xlim(s_calibrated.f[0], s_calibrated.f[-1])
plt.show()
# %%

View File

@ -21,14 +21,17 @@ dependencies = [
"pyadi-iio", "pyadi-iio",
"click", "click",
"matplotlib", "matplotlib",
"pyside6",
] ]
dynamic = ["version"] dynamic = ["version"]
[project.urls] [project.urls]
homepage = "https://git.brendanhaines.com/brendanhaines/charon" homepage = "https://pypi.org/project/charon-vna/"
repository = "https://git.brendanhaines.com/brendanhaines/charon_vna"
[project.scripts] [project.scripts]
# charon = "charon.charon:main" charon-cli = "charon_vna.cli:main"
charon-gui = "charon_vna.gui:main"
[tool.setuptools_scm] [tool.setuptools_scm]
version_file = "charon_vna/_version.py" version_file = "charon_vna/_version.py"