From 10e36db085997e7f85ab1117d7c0d4976eb8db1c Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Sun, 21 Dec 2025 14:54:54 -0500 Subject: [PATCH 01/50] Outline of floris integration --- .gitignore | 4 +- MITRotor/FlorisInterface.py | 77 ++ poetry.lock | 1925 ++++++++++++++--------------------- pyproject.toml | 3 +- 4 files changed, 854 insertions(+), 1155 deletions(-) create mode 100644 MITRotor/FlorisInterface.py diff --git a/.gitignore b/.gitignore index e626d6f..f729f42 100644 --- a/.gitignore +++ b/.gitignore @@ -187,4 +187,6 @@ poetry.toml # LSP config files pyrightconfig.json -# End of https://www.toptal.com/developers/gitignore/api/python \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/python + +.DS_Store \ No newline at end of file diff --git a/MITRotor/FlorisInterface.py b/MITRotor/FlorisInterface.py new file mode 100644 index 0000000..54da501 --- /dev/null +++ b/MITRotor/FlorisInterface.py @@ -0,0 +1,77 @@ +import numpy as np +from attrs import define, field +from typing import Literal +# FLORIS Imports +from floris.type_dec import floris_float_type, NDArrayFloat +from floris.core.turbine.operation_models import BaseOperationModel +# MITRotor Imports +from MITRotor.ReferenceTurbines import IEA15MW +from MITRotor.RotorDefinition import RotorDefinition +from MITRotor.Geometry import BEMGeometry +from MITRotor.Momentum import UnifiedMomentum +from MITRotor.BEMSolver import BEM, BEMSolution + +@define +class MITRotorTurbine(BaseOperationModel): + """ + A turbine operation model that calls MITRotor. + """ + # user can define a BEM model if they want a different rotor, momentum model, or geometry + default_bem = BEM( + rotor=IEA15MW(), + momentum_model = UnifiedMomentum(averaging = "rotor"), + geometry = BEMGeometry(Nr = 10, Ntheta = 20), + ) + bem_model = field(init = False, default = default_bem, type = BEM) + # save most recent solution by unique floris arguments + _bem_solution: BEMSolution = field(init=False, default=None) + _last_key: bytes = field(init=False, default=None) + + def _get_solution_key(self, velocities: np.ndarray) -> bytes: # TODO: add more inputs + # Fast, deterministic, and explicit + return velocities.tobytes() + + def _get_solution(self, + power_thrust_table, + velocities, + air_density=None, + ): + # create cache key for current inputs + key = self._velocity_key(velocities) # TODO: add more inputs + # update solution if conditions are different + if key != self._last_key: + self._bem_solution = self.bem_model( # TODO: make sure these inputs are right + power_thrust_table, + velocities, + air_density, + ) + self._last_key = key + return self._bem_solution + + def power( + self, + velocities: NDArrayFloat, + turbulence_intensities: NDArrayFloat, + yaw_angles: NDArrayFloat, + tilt_angles: NDArrayFloat, + **_ + ) -> NDArrayFloat: + return self._get_solution( + power_thrust_table, velocities, air_density + ).power + + + def thrust_coefficient( + self, + velocities: NDArrayFloat, + **_ + ) -> NDArrayFloat: + return self._get_solution(power_thrust_table, velocities, air_density).power + + + def axial_induction( + self, + velocities: NDArrayFloat, + **_ + ) -> NDArrayFloat: + return self._get_solution(power_thrust_table, velocities, air_density).power \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 5ab5738..b1ad6e6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,29 +1,5 @@ # This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. -[[package]] -name = "anyio" -version = "4.5.2" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "anyio-4.5.2-py3-none-any.whl", hash = "sha256:c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f"}, - {file = "anyio-4.5.2.tar.gz", hash = "sha256:23009af4ed04ce05991845451e11ef02fc7c5ed29179ac9a420e5ad0ac7ddc5b"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} - -[package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21.0b1) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] -trio = ["trio (>=0.26.1)"] - [[package]] name = "anyio" version = "4.11.0" @@ -31,13 +7,13 @@ description = "High-level concurrency and networking framework on top of asyncio optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc"}, {file = "anyio-4.11.0.tar.gz", hash = "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4"}, ] [package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} @@ -52,7 +28,7 @@ description = "Disable App Nap on macOS >= 10.9" optional = false python-versions = ">=3.6" groups = ["dev"] -markers = "sys_platform == \"darwin\" and python_version <= \"3.11\" or platform_system == \"Darwin\"" +markers = "platform_system == \"Darwin\" or sys_platform == \"darwin\" and python_version < \"3.11\"" files = [ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, @@ -73,45 +49,6 @@ files = [ [package.dependencies] argon2-cffi-bindings = "*" -[[package]] -name = "argon2-cffi-bindings" -version = "21.2.0" -description = "Low-level CFFI bindings for Argon2" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, - {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, -] - -[package.dependencies] -cffi = ">=1.0.1" - -[package.extras] -dev = ["cogapp", "pre-commit", "pytest", "wheel"] -tests = ["pytest"] - [[package]] name = "argon2-cffi-bindings" version = "25.1.0" @@ -119,7 +56,6 @@ description = "Low-level CFFI bindings for Argon2" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f"}, {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b"}, @@ -168,7 +104,6 @@ files = [ ] [package.dependencies] -"backports.zoneinfo" = {version = "0.2.1", markers = "python_version < \"3.9\""} python-dateutil = ">=2.7.0" tzdata = {version = "*", markers = "python_version >= \"3.9\""} @@ -192,22 +127,6 @@ files = [ astroid = ["astroid (>=2,<4)"] test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] -[[package]] -name = "async-lru" -version = "2.0.4" -description = "Simple LRU cache for asyncio" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"}, - {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} - [[package]] name = "async-lru" version = "2.0.5" @@ -215,32 +134,13 @@ description = "Simple LRU cache for asyncio" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "async_lru-2.0.5-py3-none-any.whl", hash = "sha256:ab95404d8d2605310d345932697371a5f40def0487c03d6d0ad9138de52c9943"}, {file = "async_lru-2.0.5.tar.gz", hash = "sha256:481d52ccdd27275f42c43a928b4a50c3bfb2d67af4e78b170e3e0bb39c66e5bb"}, ] -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] +[package.dependencies] +typing_extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "attrs" @@ -248,8 +148,7 @@ version = "25.4.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.9" -groups = ["dev"] -markers = "python_version >= \"3.12\"" +groups = ["main", "dev"] files = [ {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"}, {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"}, @@ -267,9 +166,6 @@ files = [ {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, ] -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} - [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] @@ -280,42 +176,12 @@ description = "Specifications for callback functions passed in to an API" optional = false python-versions = "*" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] -[[package]] -name = "backports-zoneinfo" -version = "0.2.1" -description = "Backport of the standard library zoneinfo module" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -markers = "python_version == \"3.8\"" -files = [ - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"}, - {file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"}, -] - -[package.extras] -tzdata = ["tzdata"] - [[package]] name = "beautifulsoup4" version = "4.14.2" @@ -395,7 +261,7 @@ description = "An easy safelist-based HTML-sanitizing tool." optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, @@ -416,7 +282,7 @@ description = "An easy safelist-based HTML-sanitizing tool." optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6"}, {file = "bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22"}, @@ -441,87 +307,6 @@ files = [ {file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"}, ] -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - [[package]] name = "cffi" version = "2.0.0" @@ -529,7 +314,6 @@ description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -750,7 +534,7 @@ description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -766,7 +550,7 @@ description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc"}, {file = "click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"}, @@ -788,6 +572,24 @@ files = [ ] markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\"", examples = "platform_system == \"Windows\""} +[[package]] +name = "coloredlogs" +version = "15.0.1" +description = "Colored terminal output for Python's logging module" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] +files = [ + {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, + {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, +] + +[package.dependencies] +humanfriendly = ">=9.1" + +[package.extras] +cron = ["capturer (>=2.4)"] + [[package]] name = "comm" version = "0.2.3" @@ -805,76 +607,89 @@ test = ["pytest"] [[package]] name = "contourpy" -version = "1.1.1" +version = "1.3.0" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false -python-versions = ">=3.8" -groups = ["examples"] -markers = "python_version <= \"3.11\"" +python-versions = ">=3.9" +groups = ["main", "examples"] +markers = "python_version < \"3.11\"" files = [ - {file = "contourpy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:46e24f5412c948d81736509377e255f6040e94216bf1a9b5ea1eaa9d29f6ec1b"}, - {file = "contourpy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e48694d6a9c5a26ee85b10130c77a011a4fedf50a7279fa0bdaf44bafb4299d"}, - {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a66045af6cf00e19d02191ab578a50cb93b2028c3eefed999793698e9ea768ae"}, - {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ebf42695f75ee1a952f98ce9775c873e4971732a87334b099dde90b6af6a916"}, - {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6aec19457617ef468ff091669cca01fa7ea557b12b59a7908b9474bb9674cf0"}, - {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:462c59914dc6d81e0b11f37e560b8a7c2dbab6aca4f38be31519d442d6cde1a1"}, - {file = "contourpy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6d0a8efc258659edc5299f9ef32d8d81de8b53b45d67bf4bfa3067f31366764d"}, - {file = "contourpy-1.1.1-cp310-cp310-win32.whl", hash = "sha256:d6ab42f223e58b7dac1bb0af32194a7b9311065583cc75ff59dcf301afd8a431"}, - {file = "contourpy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:549174b0713d49871c6dee90a4b499d3f12f5e5f69641cd23c50a4542e2ca1eb"}, - {file = "contourpy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:407d864db716a067cc696d61fa1ef6637fedf03606e8417fe2aeed20a061e6b2"}, - {file = "contourpy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe80c017973e6a4c367e037cb31601044dd55e6bfacd57370674867d15a899b"}, - {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e30aaf2b8a2bac57eb7e1650df1b3a4130e8d0c66fc2f861039d507a11760e1b"}, - {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3de23ca4f381c3770dee6d10ead6fff524d540c0f662e763ad1530bde5112532"}, - {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:566f0e41df06dfef2431defcfaa155f0acfa1ca4acbf8fd80895b1e7e2ada40e"}, - {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04c2f0adaf255bf756cf08ebef1be132d3c7a06fe6f9877d55640c5e60c72c5"}, - {file = "contourpy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0c188ae66b772d9d61d43c6030500344c13e3f73a00d1dc241da896f379bb62"}, - {file = "contourpy-1.1.1-cp311-cp311-win32.whl", hash = "sha256:0683e1ae20dc038075d92e0e0148f09ffcefab120e57f6b4c9c0f477ec171f33"}, - {file = "contourpy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:8636cd2fc5da0fb102a2504fa2c4bea3cbc149533b345d72cdf0e7a924decc45"}, - {file = "contourpy-1.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:560f1d68a33e89c62da5da4077ba98137a5e4d3a271b29f2f195d0fba2adcb6a"}, - {file = "contourpy-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24216552104ae8f3b34120ef84825400b16eb6133af2e27a190fdc13529f023e"}, - {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56de98a2fb23025882a18b60c7f0ea2d2d70bbbcfcf878f9067234b1c4818442"}, - {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:07d6f11dfaf80a84c97f1a5ba50d129d9303c5b4206f776e94037332e298dda8"}, - {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1eaac5257a8f8a047248d60e8f9315c6cff58f7803971170d952555ef6344a7"}, - {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19557fa407e70f20bfaba7d55b4d97b14f9480856c4fb65812e8a05fe1c6f9bf"}, - {file = "contourpy-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:081f3c0880712e40effc5f4c3b08feca6d064cb8cfbb372ca548105b86fd6c3d"}, - {file = "contourpy-1.1.1-cp312-cp312-win32.whl", hash = "sha256:059c3d2a94b930f4dafe8105bcdc1b21de99b30b51b5bce74c753686de858cb6"}, - {file = "contourpy-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f44d78b61740e4e8c71db1cf1fd56d9050a4747681c59ec1094750a658ceb970"}, - {file = "contourpy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:70e5a10f8093d228bb2b552beeb318b8928b8a94763ef03b858ef3612b29395d"}, - {file = "contourpy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8394e652925a18ef0091115e3cc191fef350ab6dc3cc417f06da66bf98071ae9"}, - {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5bd5680f844c3ff0008523a71949a3ff5e4953eb7701b28760805bc9bcff217"}, - {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66544f853bfa85c0d07a68f6c648b2ec81dafd30f272565c37ab47a33b220684"}, - {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0c02b75acfea5cab07585d25069207e478d12309557f90a61b5a3b4f77f46ce"}, - {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41339b24471c58dc1499e56783fedc1afa4bb018bcd035cfb0ee2ad2a7501ef8"}, - {file = "contourpy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f29fb0b3f1217dfe9362ec55440d0743fe868497359f2cf93293f4b2701b8251"}, - {file = "contourpy-1.1.1-cp38-cp38-win32.whl", hash = "sha256:f9dc7f933975367251c1b34da882c4f0e0b2e24bb35dc906d2f598a40b72bfc7"}, - {file = "contourpy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:498e53573e8b94b1caeb9e62d7c2d053c263ebb6aa259c81050766beb50ff8d9"}, - {file = "contourpy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ba42e3810999a0ddd0439e6e5dbf6d034055cdc72b7c5c839f37a7c274cb4eba"}, - {file = "contourpy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c06e4c6e234fcc65435223c7b2a90f286b7f1b2733058bdf1345d218cc59e34"}, - {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca6fab080484e419528e98624fb5c4282148b847e3602dc8dbe0cb0669469887"}, - {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93df44ab351119d14cd1e6b52a5063d3336f0754b72736cc63db59307dabb718"}, - {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eafbef886566dc1047d7b3d4b14db0d5b7deb99638d8e1be4e23a7c7ac59ff0f"}, - {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efe0fab26d598e1ec07d72cf03eaeeba8e42b4ecf6b9ccb5a356fde60ff08b85"}, - {file = "contourpy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f08e469821a5e4751c97fcd34bcb586bc243c39c2e39321822060ba902eac49e"}, - {file = "contourpy-1.1.1-cp39-cp39-win32.whl", hash = "sha256:bfc8a5e9238232a45ebc5cb3bfee71f1167064c8d382cadd6076f0d51cff1da0"}, - {file = "contourpy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c84fdf3da00c2827d634de4fcf17e3e067490c4aea82833625c4c8e6cdea0887"}, - {file = "contourpy-1.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:229a25f68046c5cf8067d6d6351c8b99e40da11b04d8416bf8d2b1d75922521e"}, - {file = "contourpy-1.1.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a10dab5ea1bd4401c9483450b5b0ba5416be799bbd50fc7a6cc5e2a15e03e8a3"}, - {file = "contourpy-1.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4f9147051cb8fdb29a51dc2482d792b3b23e50f8f57e3720ca2e3d438b7adf23"}, - {file = "contourpy-1.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a75cc163a5f4531a256f2c523bd80db509a49fc23721b36dd1ef2f60ff41c3cb"}, - {file = "contourpy-1.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b53d5769aa1f2d4ea407c65f2d1d08002952fac1d9e9d307aa2e1023554a163"}, - {file = "contourpy-1.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11b836b7dbfb74e049c302bbf74b4b8f6cb9d0b6ca1bf86cfa8ba144aedadd9c"}, - {file = "contourpy-1.1.1.tar.gz", hash = "sha256:96ba37c2e24b7212a77da85004c38e7c4d155d3e72a45eeaf22c1f03f607e8ab"}, + {file = "contourpy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:880ea32e5c774634f9fcd46504bf9f080a41ad855f4fef54f5380f5133d343c7"}, + {file = "contourpy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:76c905ef940a4474a6289c71d53122a4f77766eef23c03cd57016ce19d0f7b42"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92f8557cbb07415a4d6fa191f20fd9d2d9eb9c0b61d1b2f52a8926e43c6e9af7"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36f965570cff02b874773c49bfe85562b47030805d7d8360748f3eca570f4cab"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cacd81e2d4b6f89c9f8a5b69b86490152ff39afc58a95af002a398273e5ce589"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69375194457ad0fad3a839b9e29aa0b0ed53bb54db1bfb6c3ae43d111c31ce41"}, + {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a52040312b1a858b5e31ef28c2e865376a386c60c0e248370bbea2d3f3b760d"}, + {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3faeb2998e4fcb256542e8a926d08da08977f7f5e62cf733f3c211c2a5586223"}, + {file = "contourpy-1.3.0-cp310-cp310-win32.whl", hash = "sha256:36e0cff201bcb17a0a8ecc7f454fe078437fa6bda730e695a92f2d9932bd507f"}, + {file = "contourpy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:87ddffef1dbe5e669b5c2440b643d3fdd8622a348fe1983fad7a0f0ccb1cd67b"}, + {file = "contourpy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad"}, + {file = "contourpy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:834e0cfe17ba12f79963861e0f908556b2cedd52e1f75e6578801febcc6a9f49"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4865cd1d419e0c7a7bf6de1777b185eebdc51470800a9f42b9e9decf17762081"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:303c252947ab4b14c08afeb52375b26781ccd6a5ccd81abcdfc1fafd14cf93c1"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d"}, + {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:76a896b2f195b57db25d6b44e7e03f221d32fe318d03ede41f8b4d9ba1bff53c"}, + {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e1fd23e9d01591bab45546c089ae89d926917a66dceb3abcf01f6105d927e2cb"}, + {file = "contourpy-1.3.0-cp311-cp311-win32.whl", hash = "sha256:d402880b84df3bec6eab53cd0cf802cae6a2ef9537e70cf75e91618a3801c20c"}, + {file = "contourpy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67"}, + {file = "contourpy-1.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:570ef7cf892f0afbe5b2ee410c507ce12e15a5fa91017a0009f79f7d93a1268f"}, + {file = "contourpy-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:da84c537cb8b97d153e9fb208c221c45605f73147bd4cadd23bdae915042aad6"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0be4d8425bfa755e0fd76ee1e019636ccc7c29f77a7c86b4328a9eb6a26d0639"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c0da700bf58f6e0b65312d0a5e695179a71d0163957fa381bb3c1f72972537c"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb8b141bb00fa977d9122636b16aa67d37fd40a3d8b52dd837e536d64b9a4d06"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3634b5385c6716c258d0419c46d05c8aa7dc8cb70326c9a4fb66b69ad2b52e09"}, + {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0dce35502151b6bd35027ac39ba6e5a44be13a68f55735c3612c568cac3805fd"}, + {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea348f053c645100612b333adc5983d87be69acdc6d77d3169c090d3b01dc35"}, + {file = "contourpy-1.3.0-cp312-cp312-win32.whl", hash = "sha256:90f73a5116ad1ba7174341ef3ea5c3150ddf20b024b98fb0c3b29034752c8aeb"}, + {file = "contourpy-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:b11b39aea6be6764f84360fce6c82211a9db32a7c7de8fa6dd5397cf1d079c3b"}, + {file = "contourpy-1.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3e1c7fa44aaae40a2247e2e8e0627f4bea3dd257014764aa644f319a5f8600e3"}, + {file = "contourpy-1.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:364174c2a76057feef647c802652f00953b575723062560498dc7930fc9b1cb7"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b238b3b3b649e09ce9aaf51f0c261d38644bdfa35cbaf7b263457850957a84"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d51fca85f9f7ad0b65b4b9fe800406d0d77017d7270d31ec3fb1cc07358fdea0"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:732896af21716b29ab3e988d4ce14bc5133733b85956316fb0c56355f398099b"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d73f659398a0904e125280836ae6f88ba9b178b2fed6884f3b1f95b989d2c8da"}, + {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c6c7c2408b7048082932cf4e641fa3b8ca848259212f51c8c59c45aa7ac18f14"}, + {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f317576606de89da6b7e0861cf6061f6146ead3528acabff9236458a6ba467f8"}, + {file = "contourpy-1.3.0-cp313-cp313-win32.whl", hash = "sha256:31cd3a85dbdf1fc002280c65caa7e2b5f65e4a973fcdf70dd2fdcb9868069294"}, + {file = "contourpy-1.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4553c421929ec95fb07b3aaca0fae668b2eb5a5203d1217ca7c34c063c53d087"}, + {file = "contourpy-1.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:345af746d7766821d05d72cb8f3845dfd08dd137101a2cb9b24de277d716def8"}, + {file = "contourpy-1.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3bb3808858a9dc68f6f03d319acd5f1b8a337e6cdda197f02f4b8ff67ad2057b"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:420d39daa61aab1221567b42eecb01112908b2cab7f1b4106a52caaec8d36973"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d63ee447261e963af02642ffcb864e5a2ee4cbfd78080657a9880b8b1868e18"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:167d6c890815e1dac9536dca00828b445d5d0df4d6a8c6adb4a7ec3166812fa8"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:710a26b3dc80c0e4febf04555de66f5fd17e9cf7170a7b08000601a10570bda6"}, + {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:75ee7cb1a14c617f34a51d11fa7524173e56551646828353c4af859c56b766e2"}, + {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:33c92cdae89ec5135d036e7218e69b0bb2851206077251f04a6c4e0e21f03927"}, + {file = "contourpy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a11077e395f67ffc2c44ec2418cfebed032cd6da3022a94fc227b6faf8e2acb8"}, + {file = "contourpy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e8134301d7e204c88ed7ab50028ba06c683000040ede1d617298611f9dc6240c"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e12968fdfd5bb45ffdf6192a590bd8ddd3ba9e58360b29683c6bb71a7b41edca"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd2a0fc506eccaaa7595b7e1418951f213cf8255be2600f1ea1b61e46a60c55f"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfb5c62ce023dfc410d6059c936dcf96442ba40814aefbfa575425a3a7f19dc"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68a32389b06b82c2fdd68276148d7b9275b5f5cf13e5417e4252f6d1a34f72a2"}, + {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94e848a6b83da10898cbf1311a815f770acc9b6a3f2d646f330d57eb4e87592e"}, + {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d78ab28a03c854a873787a0a42254a0ccb3cb133c672f645c9f9c8f3ae9d0800"}, + {file = "contourpy-1.3.0-cp39-cp39-win32.whl", hash = "sha256:81cb5ed4952aae6014bc9d0421dec7c5835c9c8c31cdf51910b708f548cf58e5"}, + {file = "contourpy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:14e262f67bd7e6eb6880bc564dcda30b15e351a594657e55b7eec94b6ef72843"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fe41b41505a5a33aeaed2a613dccaeaa74e0e3ead6dd6fd3a118fb471644fd6c"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca7e17a65f72a5133bdbec9ecf22401c62bcf4821361ef7811faee695799779"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ec4dc6bf570f5b22ed0d7efba0dfa9c5b9e0431aeea7581aa217542d9e809a4"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:00ccd0dbaad6d804ab259820fa7cb0b8036bda0686ef844d24125d8287178ce0"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ca947601224119117f7c19c9cdf6b3ab54c5726ef1d906aa4a69dfb6dd58102"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6ec93afeb848a0845a18989da3beca3eec2c0f852322efe21af1931147d12cb"}, + {file = "contourpy-1.3.0.tar.gz", hash = "sha256:7ffa0db17717a8ffb127efd0c95a4362d996b892c2904db72428d5b52e1938a4"}, ] [package.dependencies] -numpy = {version = ">=1.16,<2.0", markers = "python_version <= \"3.11\""} +numpy = ">=1.23" [package.extras] bokeh = ["bokeh", "selenium"] docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] -mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.4.1)", "types-Pillow"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.11.1)", "types-Pillow"] test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] -test-no-images = ["pytest", "pytest-cov", "wurlitzer"] +test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] [[package]] name = "contourpy" @@ -882,8 +697,8 @@ version = "1.3.3" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.11" -groups = ["examples"] -markers = "python_version >= \"3.12\"" +groups = ["main", "examples"] +markers = "python_version >= \"3.11\"" files = [ {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, {file = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"}, @@ -975,7 +790,7 @@ version = "0.12.1" description = "Composable style cycles" optional = false python-versions = ">=3.8" -groups = ["examples"] +groups = ["main", "examples"] files = [ {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, @@ -1049,6 +864,22 @@ files = [ {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, ] +[[package]] +name = "dill" +version = "0.4.0" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049"}, + {file = "dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + [[package]] name = "exceptiongroup" version = "1.3.0" @@ -1099,79 +930,32 @@ files = [ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] [[package]] -name = "fonttools" -version = "4.57.0" -description = "Tools to manipulate font files" +name = "floris" +version = "4.5.1" +description = "A controls-oriented engineering wake model." optional = false -python-versions = ">=3.8" -groups = ["examples"] -markers = "python_version <= \"3.11\"" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "fonttools-4.57.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:babe8d1eb059a53e560e7bf29f8e8f4accc8b6cfb9b5fd10e485bde77e71ef41"}, - {file = "fonttools-4.57.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:81aa97669cd726349eb7bd43ca540cf418b279ee3caba5e2e295fb4e8f841c02"}, - {file = "fonttools-4.57.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0e9618630edd1910ad4f07f60d77c184b2f572c8ee43305ea3265675cbbfe7e"}, - {file = "fonttools-4.57.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34687a5d21f1d688d7d8d416cb4c5b9c87fca8a1797ec0d74b9fdebfa55c09ab"}, - {file = "fonttools-4.57.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:69ab81b66ebaa8d430ba56c7a5f9abe0183afefd3a2d6e483060343398b13fb1"}, - {file = "fonttools-4.57.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d639397de852f2ccfb3134b152c741406752640a266d9c1365b0f23d7b88077f"}, - {file = "fonttools-4.57.0-cp310-cp310-win32.whl", hash = "sha256:cc066cb98b912f525ae901a24cd381a656f024f76203bc85f78fcc9e66ae5aec"}, - {file = "fonttools-4.57.0-cp310-cp310-win_amd64.whl", hash = "sha256:7a64edd3ff6a7f711a15bd70b4458611fb240176ec11ad8845ccbab4fe6745db"}, - {file = "fonttools-4.57.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3871349303bdec958360eedb619169a779956503ffb4543bb3e6211e09b647c4"}, - {file = "fonttools-4.57.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c59375e85126b15a90fcba3443eaac58f3073ba091f02410eaa286da9ad80ed8"}, - {file = "fonttools-4.57.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967b65232e104f4b0f6370a62eb33089e00024f2ce143aecbf9755649421c683"}, - {file = "fonttools-4.57.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39acf68abdfc74e19de7485f8f7396fa4d2418efea239b7061d6ed6a2510c746"}, - {file = "fonttools-4.57.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d077f909f2343daf4495ba22bb0e23b62886e8ec7c109ee8234bdbd678cf344"}, - {file = "fonttools-4.57.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:46370ac47a1e91895d40e9ad48effbe8e9d9db1a4b80888095bc00e7beaa042f"}, - {file = "fonttools-4.57.0-cp311-cp311-win32.whl", hash = "sha256:ca2aed95855506b7ae94e8f1f6217b7673c929e4f4f1217bcaa236253055cb36"}, - {file = "fonttools-4.57.0-cp311-cp311-win_amd64.whl", hash = "sha256:17168a4670bbe3775f3f3f72d23ee786bd965395381dfbb70111e25e81505b9d"}, - {file = "fonttools-4.57.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:889e45e976c74abc7256d3064aa7c1295aa283c6bb19810b9f8b604dfe5c7f31"}, - {file = "fonttools-4.57.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0425c2e052a5f1516c94e5855dbda706ae5a768631e9fcc34e57d074d1b65b92"}, - {file = "fonttools-4.57.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44c26a311be2ac130f40a96769264809d3b0cb297518669db437d1cc82974888"}, - {file = "fonttools-4.57.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c41ba992df5b8d680b89fd84c6a1f2aca2b9f1ae8a67400c8930cd4ea115f6"}, - {file = "fonttools-4.57.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ea1e9e43ca56b0c12440a7c689b1350066595bebcaa83baad05b8b2675129d98"}, - {file = "fonttools-4.57.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84fd56c78d431606332a0627c16e2a63d243d0d8b05521257d77c6529abe14d8"}, - {file = "fonttools-4.57.0-cp312-cp312-win32.whl", hash = "sha256:f4376819c1c778d59e0a31db5dc6ede854e9edf28bbfa5b756604727f7f800ac"}, - {file = "fonttools-4.57.0-cp312-cp312-win_amd64.whl", hash = "sha256:57e30241524879ea10cdf79c737037221f77cc126a8cdc8ff2c94d4a522504b9"}, - {file = "fonttools-4.57.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:408ce299696012d503b714778d89aa476f032414ae57e57b42e4b92363e0b8ef"}, - {file = "fonttools-4.57.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bbceffc80aa02d9e8b99f2a7491ed8c4a783b2fc4020119dc405ca14fb5c758c"}, - {file = "fonttools-4.57.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f022601f3ee9e1f6658ed6d184ce27fa5216cee5b82d279e0f0bde5deebece72"}, - {file = "fonttools-4.57.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dea5893b58d4637ffa925536462ba626f8a1b9ffbe2f5c272cdf2c6ebadb817"}, - {file = "fonttools-4.57.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dff02c5c8423a657c550b48231d0a48d7e2b2e131088e55983cfe74ccc2c7cc9"}, - {file = "fonttools-4.57.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:767604f244dc17c68d3e2dbf98e038d11a18abc078f2d0f84b6c24571d9c0b13"}, - {file = "fonttools-4.57.0-cp313-cp313-win32.whl", hash = "sha256:8e2e12d0d862f43d51e5afb8b9751c77e6bec7d2dc00aad80641364e9df5b199"}, - {file = "fonttools-4.57.0-cp313-cp313-win_amd64.whl", hash = "sha256:f1d6bc9c23356908db712d282acb3eebd4ae5ec6d8b696aa40342b1d84f8e9e3"}, - {file = "fonttools-4.57.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9d57b4e23ebbe985125d3f0cabbf286efa191ab60bbadb9326091050d88e8213"}, - {file = "fonttools-4.57.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:579ba873d7f2a96f78b2e11028f7472146ae181cae0e4d814a37a09e93d5c5cc"}, - {file = "fonttools-4.57.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e3e1ec10c29bae0ea826b61f265ec5c858c5ba2ce2e69a71a62f285cf8e4595"}, - {file = "fonttools-4.57.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1968f2a2003c97c4ce6308dc2498d5fd4364ad309900930aa5a503c9851aec8"}, - {file = "fonttools-4.57.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:aff40f8ac6763d05c2c8f6d240c6dac4bb92640a86d9b0c3f3fff4404f34095c"}, - {file = "fonttools-4.57.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d07f1b64008e39fceae7aa99e38df8385d7d24a474a8c9872645c4397b674481"}, - {file = "fonttools-4.57.0-cp38-cp38-win32.whl", hash = "sha256:51d8482e96b28fb28aa8e50b5706f3cee06de85cbe2dce80dbd1917ae22ec5a6"}, - {file = "fonttools-4.57.0-cp38-cp38-win_amd64.whl", hash = "sha256:03290e818782e7edb159474144fca11e36a8ed6663d1fcbd5268eb550594fd8e"}, - {file = "fonttools-4.57.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7339e6a3283e4b0ade99cade51e97cde3d54cd6d1c3744459e886b66d630c8b3"}, - {file = "fonttools-4.57.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:05efceb2cb5f6ec92a4180fcb7a64aa8d3385fd49cfbbe459350229d1974f0b1"}, - {file = "fonttools-4.57.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a97bb05eb24637714a04dee85bdf0ad1941df64fe3b802ee4ac1c284a5f97b7c"}, - {file = "fonttools-4.57.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:541cb48191a19ceb1a2a4b90c1fcebd22a1ff7491010d3cf840dd3a68aebd654"}, - {file = "fonttools-4.57.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:cdef9a056c222d0479a1fdb721430f9efd68268014c54e8166133d2643cb05d9"}, - {file = "fonttools-4.57.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3cf97236b192a50a4bf200dc5ba405aa78d4f537a2c6e4c624bb60466d5b03bd"}, - {file = "fonttools-4.57.0-cp39-cp39-win32.whl", hash = "sha256:e952c684274a7714b3160f57ec1d78309f955c6335c04433f07d36c5eb27b1f9"}, - {file = "fonttools-4.57.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2a722c0e4bfd9966a11ff55c895c817158fcce1b2b6700205a376403b546ad9"}, - {file = "fonttools-4.57.0-py3-none-any.whl", hash = "sha256:3122c604a675513c68bd24c6a8f9091f1c2376d18e8f5fe5a101746c81b3e98f"}, - {file = "fonttools-4.57.0.tar.gz", hash = "sha256:727ece10e065be2f9dd239d15dd5d60a66e17eac11aea47d447f9f03fdbc42de"}, + {file = "floris-4.5.1-py3-none-any.whl", hash = "sha256:85dd2669319c3f4987a8231862eb2cb219c6738c9c042135f734d95b593d6961"}, + {file = "floris-4.5.1.tar.gz", hash = "sha256:7823f1a0d1d286fe2e6347972aaaef70d219b95e1c01e579e1bfadfd14a12504"}, ] +[package.dependencies] +attrs = "*" +coloredlogs = ">=15.0,<16.0" +matplotlib = ">=3.0,<4.0" +numexpr = ">=2.0,<3.0" +numpy = ">=2.0,<3.0" +pandas = ">=2.0,<3.0" +pathos = ">=0.3,<1.0" +pyyaml = ">=6.0,<7.0" +scipy = ">=1.1,<2.0" +shapely = ">=2.0,<3.0" + [package.extras] -all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0) ; python_version <= \"3.12\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] -graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] -lxml = ["lxml (>=4.0)"] -pathops = ["skia-pathops (>=0.5.0)"] -plot = ["matplotlib"] -repacker = ["uharfbuzz (>=0.23.0)"] -symfont = ["sympy"] -type1 = ["xattr ; sys_platform == \"darwin\""] -ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=15.1.0) ; python_version <= \"3.12\""] -woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] +develop = ["isort (>=5.0,<6.0)", "pre-commit (>=4.0,<5.0)", "pytest (>=8.0,<9.0)", "pytest-benchmark (>=5.1,<6.0)", "ruff (>=0.9,<1.0)"] +docs = ["bokeh (>=3.7,<4.0)", "jupyter-book (>=1.0,<2.0)", "sphinx-autodoc-typehints (>=2.0,<3.0)", "sphinx-book-theme (>=1.0,<2.0)", "sphinxcontrib-autoyaml (>=1.0,<2.0)", "sphinxcontrib.mermaid (>=1.0,<2.0)"] [[package]] name = "fonttools" @@ -1179,8 +963,7 @@ version = "4.60.1" description = "Tools to manipulate font files" optional = false python-versions = ">=3.9" -groups = ["examples"] -markers = "python_version >= \"3.12\"" +groups = ["main", "examples"] files = [ {file = "fonttools-4.60.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9a52f254ce051e196b8fe2af4634c2d2f02c981756c6464dc192f1b6050b4e28"}, {file = "fonttools-4.60.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7420a2696a44650120cdd269a5d2e56a477e2bfa9d95e86229059beb1c19e15"}, @@ -1341,6 +1124,21 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "humanfriendly" +version = "10.0" +description = "Human friendly output for text interfaces using Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] +files = [ + {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, + {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, +] + +[package.dependencies] +pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} + [[package]] name = "idna" version = "3.11" @@ -1363,7 +1161,7 @@ description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version < \"3.10\"" +markers = "python_version == \"3.9\"" files = [ {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, @@ -1387,12 +1185,12 @@ version = "6.4.5" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" -groups = ["dev", "examples"] +groups = ["main", "examples"] +markers = "python_version == \"3.9\"" files = [ {file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"}, {file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"}, ] -markers = {dev = "python_version == \"3.8\"", examples = "python_version < \"3.10\""} [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} @@ -1412,7 +1210,7 @@ description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -1425,47 +1223,12 @@ description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, ] -[[package]] -name = "ipykernel" -version = "6.29.5" -description = "IPython Kernel for Jupyter" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, - {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, -] - -[package.dependencies] -appnope = {version = "*", markers = "platform_system == \"Darwin\""} -comm = ">=0.1.1" -debugpy = ">=1.6.5" -ipython = ">=7.23.1" -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -matplotlib-inline = ">=0.1" -nest-asyncio = "*" -packaging = "*" -psutil = "*" -pyzmq = ">=24" -tornado = ">=6.1" -traitlets = ">=5.4.0" - -[package.extras] -cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] -pyqt5 = ["pyqt5"] -pyside6 = ["pyside6"] -test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] - [[package]] name = "ipykernel" version = "6.31.0" @@ -1473,7 +1236,6 @@ description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "ipykernel-6.31.0-py3-none-any.whl", hash = "sha256:abe5386f6ced727a70e0eb0cf1da801fa7c5fa6ff82147747d5a0406cd8c94af"}, {file = "ipykernel-6.31.0.tar.gz", hash = "sha256:2372ce8bc1ff4f34e58cafed3a0feb2194b91fc7cad0fc72e79e47b45ee9e8f6"}, @@ -1508,7 +1270,7 @@ description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "ipython-8.12.3-py3-none-any.whl", hash = "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c"}, {file = "ipython-8.12.3.tar.gz", hash = "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363"}, @@ -1549,7 +1311,7 @@ description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2"}, {file = "ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216"}, @@ -1565,6 +1327,7 @@ prompt_toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack_data = "*" traitlets = ">=5.13.0" +typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] @@ -1682,39 +1445,6 @@ files = [ {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, ] -[[package]] -name = "jsonschema" -version = "4.23.0" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, - {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} -jsonschema-specifications = ">=2023.03.6" -pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} -referencing = ">=0.28.4" -rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} -rpds-py = ">=0.7.1" -uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] - [[package]] name = "jsonschema" version = "4.25.1" @@ -1722,7 +1452,6 @@ description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"}, {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"}, @@ -1747,23 +1476,6 @@ webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] -[[package]] -name = "jsonschema-specifications" -version = "2023.12.1" -description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, - {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, -] - -[package.dependencies] -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -referencing = ">=0.31.0" - [[package]] name = "jsonschema-specifications" version = "2025.9.1" @@ -1771,7 +1483,6 @@ description = "The JSON Schema meta-schemas and vocabularies, exposed as a Regis optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, @@ -1856,7 +1567,7 @@ description = "Jupyter core package. A base package on which Jupyter projects re optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "jupyter_core-5.8.1-py3-none-any.whl", hash = "sha256:c28d268fc90fb53f1338ded2eb410704c5449a358406e8a948b75706e24863d0"}, {file = "jupyter_core-5.8.1.tar.gz", hash = "sha256:0a5f9706f70e64786b75acba995988915ebd4601c8a52e534a40b51c95f59941"}, @@ -1878,7 +1589,7 @@ description = "Jupyter core package. A base package on which Jupyter projects re optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407"}, {file = "jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508"}, @@ -1892,33 +1603,6 @@ traitlets = ">=5.3" docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest (<9)", "pytest-cov", "pytest-timeout"] -[[package]] -name = "jupyter-events" -version = "0.10.0" -description = "Jupyter Event System library" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "jupyter_events-0.10.0-py3-none-any.whl", hash = "sha256:4b72130875e59d57716d327ea70d3ebc3af1944d3717e5a498b8a06c6c159960"}, - {file = "jupyter_events-0.10.0.tar.gz", hash = "sha256:670b8229d3cc882ec782144ed22e0d29e1c2d639263f92ca8383e66682845e22"}, -] - -[package.dependencies] -jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} -python-json-logger = ">=2.0.4" -pyyaml = ">=5.3" -referencing = "*" -rfc3339-validator = "*" -rfc3986-validator = ">=0.1.1" -traitlets = ">=5.3" - -[package.extras] -cli = ["click", "rich"] -docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] -test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] - [[package]] name = "jupyter-events" version = "0.12.0" @@ -1926,7 +1610,6 @@ description = "Jupyter Event System library" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb"}, {file = "jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b"}, @@ -1963,44 +1646,6 @@ files = [ importlib_metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} jupyter_server = ">=1.1.2" -[[package]] -name = "jupyter-server" -version = "2.14.2" -description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "jupyter_server-2.14.2-py3-none-any.whl", hash = "sha256:47ff506127c2f7851a17bf4713434208fc490955d0e8632e95014a9a9afbeefd"}, - {file = "jupyter_server-2.14.2.tar.gz", hash = "sha256:66095021aa9638ced276c248b1d81862e4c50f292d575920bbe960de1c56b12b"}, -] - -[package.dependencies] -anyio = ">=3.1.0" -argon2-cffi = ">=21.1" -jinja2 = ">=3.0.3" -jupyter-client = ">=7.4.4" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -jupyter-events = ">=0.9.0" -jupyter-server-terminals = ">=0.4.4" -nbconvert = ">=6.4.4" -nbformat = ">=5.3.0" -overrides = ">=5.0" -packaging = ">=22.0" -prometheus-client = ">=0.9" -pywinpty = {version = ">=2.0.1", markers = "os_name == \"nt\""} -pyzmq = ">=24" -send2trash = ">=1.8.2" -terminado = ">=0.8.3" -tornado = ">=6.2.0" -traitlets = ">=5.6.0" -websocket-client = ">=1.7" - -[package.extras] -docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] -test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] - [[package]] name = "jupyter-server" version = "2.17.0" @@ -2008,7 +1653,6 @@ description = "The backend—i.e. core services, APIs, and REST endpoints—to J optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f"}, {file = "jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5"}, @@ -2024,6 +1668,7 @@ jupyter-events = ">=0.11.0" jupyter-server-terminals = ">=0.4.4" nbconvert = ">=6.4.4" nbformat = ">=5.3.0" +overrides = {version = ">=5.0", markers = "python_version < \"3.12\""} packaging = ">=22.0" prometheus-client = ">=0.9" pywinpty = {version = ">=2.0.1", markers = "os_name == \"nt\""} @@ -2058,44 +1703,6 @@ terminado = ">=0.8.3" docs = ["jinja2", "jupyter-server", "mistune (<4.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] -[[package]] -name = "jupyterlab" -version = "4.3.8" -description = "JupyterLab computational environment" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "jupyterlab-4.3.8-py3-none-any.whl", hash = "sha256:8c6451ef224a18b457975fd52010e45a7aef58b719dfb242c5f253e0e48ea047"}, - {file = "jupyterlab-4.3.8.tar.gz", hash = "sha256:2ffd0e7b82786dba54743f4d1646130642ed81cb9e52f0a31e79416f6e5ba2e7"}, -] - -[package.dependencies] -async-lru = ">=1.0.0" -httpx = ">=0.25.0" -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -importlib-resources = {version = ">=1.4", markers = "python_version < \"3.9\""} -ipykernel = ">=6.5.0" -jinja2 = ">=3.0.3" -jupyter-core = "*" -jupyter-lsp = ">=2.0.0" -jupyter-server = ">=2.4.0,<3" -jupyterlab-server = ">=2.27.1,<3" -notebook-shim = ">=0.2" -packaging = "*" -setuptools = ">=41.1.0" -tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} -tornado = ">=6.2.0" -traitlets = "*" - -[package.extras] -dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.6.9)"] -docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<8.1.0)", "sphinx-copybutton"] -docs-screenshots = ["altair (==5.5.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.5)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.2.post3)", "matplotlib (==3.9.2)", "nbconvert (>=7.0.0)", "pandas (==2.2.3)", "scipy (==1.14.1)", "vega-datasets (==0.9.0)"] -test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] -upgrade-extension = ["copier (>=9,<10)", "jinja2-time (<0.3)", "pydantic (<3.0)", "pyyaml-include (<3.0)", "tomli-w (<2.0)"] - [[package]] name = "jupyterlab" version = "4.4.10" @@ -2103,7 +1710,6 @@ description = "JupyterLab computational environment" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "jupyterlab-4.4.10-py3-none-any.whl", hash = "sha256:65939ab4c8dcd0c42185c2d0d1a9d60b254dc8c46fc4fdb286b63c51e9358e07"}, {file = "jupyterlab-4.4.10.tar.gz", hash = "sha256:521c017508af4e1d6d9d8a9d90f47a11c61197ad63b2178342489de42540a615"}, @@ -2112,6 +1718,7 @@ files = [ [package.dependencies] async-lru = ">=1.0.0" httpx = ">=0.25.0,<1" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} ipykernel = ">=6.5.0,<6.30.0 || >6.30.0" jinja2 = ">=3.0.3" jupyter-core = "*" @@ -2121,6 +1728,7 @@ jupyterlab-server = ">=2.27.1,<3" notebook-shim = ">=0.2" packaging = "*" setuptools = ">=41.1.0" +tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} tornado = ">=6.2.0" traitlets = "*" @@ -2188,8 +1796,8 @@ version = "1.4.7" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.8" -groups = ["examples"] -markers = "python_version <= \"3.11\"" +groups = ["main", "examples"] +markers = "python_version < \"3.11\"" files = [ {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6"}, {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17"}, @@ -2313,8 +1921,8 @@ version = "1.4.9" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.10" -groups = ["examples"] -markers = "python_version >= \"3.12\"" +groups = ["main", "examples"] +markers = "python_version >= \"3.11\"" files = [ {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b"}, {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f"}, @@ -2426,7 +2034,6 @@ description = "a modern parsing library" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12"}, {file = "lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905"}, @@ -2438,77 +2045,6 @@ interegular = ["interegular (>=0.3.1,<0.4.0)"] nearley = ["js2py"] regex = ["regex"] -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - [[package]] name = "markupsafe" version = "3.0.3" @@ -2516,7 +2052,6 @@ description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, @@ -2611,60 +2146,54 @@ files = [ [[package]] name = "matplotlib" -version = "3.7.5" +version = "3.9.4" description = "Python plotting package" optional = false -python-versions = ">=3.8" -groups = ["examples"] -markers = "python_version <= \"3.11\"" +python-versions = ">=3.9" +groups = ["main", "examples"] +markers = "python_version < \"3.11\"" files = [ - {file = "matplotlib-3.7.5-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:4a87b69cb1cb20943010f63feb0b2901c17a3b435f75349fd9865713bfa63925"}, - {file = "matplotlib-3.7.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d3ce45010fefb028359accebb852ca0c21bd77ec0f281952831d235228f15810"}, - {file = "matplotlib-3.7.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fbea1e762b28400393d71be1a02144aa16692a3c4c676ba0178ce83fc2928fdd"}, - {file = "matplotlib-3.7.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec0e1adc0ad70ba8227e957551e25a9d2995e319c29f94a97575bb90fa1d4469"}, - {file = "matplotlib-3.7.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6738c89a635ced486c8a20e20111d33f6398a9cbebce1ced59c211e12cd61455"}, - {file = "matplotlib-3.7.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1210b7919b4ed94b5573870f316bca26de3e3b07ffdb563e79327dc0e6bba515"}, - {file = "matplotlib-3.7.5-cp310-cp310-win32.whl", hash = "sha256:068ebcc59c072781d9dcdb82f0d3f1458271c2de7ca9c78f5bd672141091e9e1"}, - {file = "matplotlib-3.7.5-cp310-cp310-win_amd64.whl", hash = "sha256:f098ffbaab9df1e3ef04e5a5586a1e6b1791380698e84938d8640961c79b1fc0"}, - {file = "matplotlib-3.7.5-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:f65342c147572673f02a4abec2d5a23ad9c3898167df9b47c149f32ce61ca078"}, - {file = "matplotlib-3.7.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4ddf7fc0e0dc553891a117aa083039088d8a07686d4c93fb8a810adca68810af"}, - {file = "matplotlib-3.7.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0ccb830fc29442360d91be48527809f23a5dcaee8da5f4d9b2d5b867c1b087b8"}, - {file = "matplotlib-3.7.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efc6bb28178e844d1f408dd4d6341ee8a2e906fc9e0fa3dae497da4e0cab775d"}, - {file = "matplotlib-3.7.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b15c4c2d374f249f324f46e883340d494c01768dd5287f8bc00b65b625ab56c"}, - {file = "matplotlib-3.7.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d028555421912307845e59e3de328260b26d055c5dac9b182cc9783854e98fb"}, - {file = "matplotlib-3.7.5-cp311-cp311-win32.whl", hash = "sha256:fe184b4625b4052fa88ef350b815559dd90cc6cc8e97b62f966e1ca84074aafa"}, - {file = "matplotlib-3.7.5-cp311-cp311-win_amd64.whl", hash = "sha256:084f1f0f2f1010868c6f1f50b4e1c6f2fb201c58475494f1e5b66fed66093647"}, - {file = "matplotlib-3.7.5-cp312-cp312-macosx_10_12_universal2.whl", hash = "sha256:34bceb9d8ddb142055ff27cd7135f539f2f01be2ce0bafbace4117abe58f8fe4"}, - {file = "matplotlib-3.7.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c5a2134162273eb8cdfd320ae907bf84d171de948e62180fa372a3ca7cf0f433"}, - {file = "matplotlib-3.7.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:039ad54683a814002ff37bf7981aa1faa40b91f4ff84149beb53d1eb64617980"}, - {file = "matplotlib-3.7.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d742ccd1b09e863b4ca58291728db645b51dab343eebb08d5d4b31b308296ce"}, - {file = "matplotlib-3.7.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:743b1c488ca6a2bc7f56079d282e44d236bf375968bfd1b7ba701fd4d0fa32d6"}, - {file = "matplotlib-3.7.5-cp312-cp312-win_amd64.whl", hash = "sha256:fbf730fca3e1f23713bc1fae0a57db386e39dc81ea57dc305c67f628c1d7a342"}, - {file = "matplotlib-3.7.5-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:cfff9b838531698ee40e40ea1a8a9dc2c01edb400b27d38de6ba44c1f9a8e3d2"}, - {file = "matplotlib-3.7.5-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:1dbcca4508bca7847fe2d64a05b237a3dcaec1f959aedb756d5b1c67b770c5ee"}, - {file = "matplotlib-3.7.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4cdf4ef46c2a1609a50411b66940b31778db1e4b73d4ecc2eaa40bd588979b13"}, - {file = "matplotlib-3.7.5-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:167200ccfefd1674b60e957186dfd9baf58b324562ad1a28e5d0a6b3bea77905"}, - {file = "matplotlib-3.7.5-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:53e64522934df6e1818b25fd48cf3b645b11740d78e6ef765fbb5fa5ce080d02"}, - {file = "matplotlib-3.7.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e3bc79b2d7d615067bd010caff9243ead1fc95cf735c16e4b2583173f717eb"}, - {file = "matplotlib-3.7.5-cp38-cp38-win32.whl", hash = "sha256:6b641b48c6819726ed47c55835cdd330e53747d4efff574109fd79b2d8a13748"}, - {file = "matplotlib-3.7.5-cp38-cp38-win_amd64.whl", hash = "sha256:f0b60993ed3488b4532ec6b697059897891927cbfc2b8d458a891b60ec03d9d7"}, - {file = "matplotlib-3.7.5-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:090964d0afaff9c90e4d8de7836757e72ecfb252fb02884016d809239f715651"}, - {file = "matplotlib-3.7.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:9fc6fcfbc55cd719bc0bfa60bde248eb68cf43876d4c22864603bdd23962ba25"}, - {file = "matplotlib-3.7.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7cc3078b019bb863752b8b60e8b269423000f1603cb2299608231996bd9d54"}, - {file = "matplotlib-3.7.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e4e9a868e8163abaaa8259842d85f949a919e1ead17644fb77a60427c90473c"}, - {file = "matplotlib-3.7.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa7ebc995a7d747dacf0a717d0eb3aa0f0c6a0e9ea88b0194d3a3cd241a1500f"}, - {file = "matplotlib-3.7.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3785bfd83b05fc0e0c2ae4c4a90034fe693ef96c679634756c50fe6efcc09856"}, - {file = "matplotlib-3.7.5-cp39-cp39-win32.whl", hash = "sha256:29b058738c104d0ca8806395f1c9089dfe4d4f0f78ea765c6c704469f3fffc81"}, - {file = "matplotlib-3.7.5-cp39-cp39-win_amd64.whl", hash = "sha256:fd4028d570fa4b31b7b165d4a685942ae9cdc669f33741e388c01857d9723eab"}, - {file = "matplotlib-3.7.5-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2a9a3f4d6a7f88a62a6a18c7e6a84aedcaf4faf0708b4ca46d87b19f1b526f88"}, - {file = "matplotlib-3.7.5-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9b3fd853d4a7f008a938df909b96db0b454225f935d3917520305b90680579c"}, - {file = "matplotlib-3.7.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0ad550da9f160737d7890217c5eeed4337d07e83ca1b2ca6535078f354e7675"}, - {file = "matplotlib-3.7.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:20da7924a08306a861b3f2d1da0d1aa9a6678e480cf8eacffe18b565af2813e7"}, - {file = "matplotlib-3.7.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b45c9798ea6bb920cb77eb7306409756a7fab9db9b463e462618e0559aecb30e"}, - {file = "matplotlib-3.7.5-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a99866267da1e561c7776fe12bf4442174b79aac1a47bd7e627c7e4d077ebd83"}, - {file = "matplotlib-3.7.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b6aa62adb6c268fc87d80f963aca39c64615c31830b02697743c95590ce3fbb"}, - {file = "matplotlib-3.7.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e530ab6a0afd082d2e9c17eb1eb064a63c5b09bb607b2b74fa41adbe3e162286"}, - {file = "matplotlib-3.7.5.tar.gz", hash = "sha256:1e5c971558ebc811aa07f54c7b7c677d78aa518ef4c390e14673a09e0860184a"}, + {file = "matplotlib-3.9.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c5fdd7abfb706dfa8d307af64a87f1a862879ec3cd8d0ec8637458f0885b9c50"}, + {file = "matplotlib-3.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d89bc4e85e40a71d1477780366c27fb7c6494d293e1617788986f74e2a03d7ff"}, + {file = "matplotlib-3.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddf9f3c26aae695c5daafbf6b94e4c1a30d6cd617ba594bbbded3b33a1fcfa26"}, + {file = "matplotlib-3.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18ebcf248030173b59a868fda1fe42397253f6698995b55e81e1f57431d85e50"}, + {file = "matplotlib-3.9.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:974896ec43c672ec23f3f8c648981e8bc880ee163146e0312a9b8def2fac66f5"}, + {file = "matplotlib-3.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:4598c394ae9711cec135639374e70871fa36b56afae17bdf032a345be552a88d"}, + {file = "matplotlib-3.9.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d4dd29641d9fb8bc4492420c5480398dd40a09afd73aebe4eb9d0071a05fbe0c"}, + {file = "matplotlib-3.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30e5b22e8bcfb95442bf7d48b0d7f3bdf4a450cbf68986ea45fca3d11ae9d099"}, + {file = "matplotlib-3.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bb0030d1d447fd56dcc23b4c64a26e44e898f0416276cac1ebc25522e0ac249"}, + {file = "matplotlib-3.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aca90ed222ac3565d2752b83dbb27627480d27662671e4d39da72e97f657a423"}, + {file = "matplotlib-3.9.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a181b2aa2906c608fcae72f977a4a2d76e385578939891b91c2550c39ecf361e"}, + {file = "matplotlib-3.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:1f6882828231eca17f501c4dcd98a05abb3f03d157fbc0769c6911fe08b6cfd3"}, + {file = "matplotlib-3.9.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:dfc48d67e6661378a21c2983200a654b72b5c5cdbd5d2cf6e5e1ece860f0cc70"}, + {file = "matplotlib-3.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47aef0fab8332d02d68e786eba8113ffd6f862182ea2999379dec9e237b7e483"}, + {file = "matplotlib-3.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fba1f52c6b7dc764097f52fd9ab627b90db452c9feb653a59945de16752e965f"}, + {file = "matplotlib-3.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:173ac3748acaac21afcc3fa1633924609ba1b87749006bc25051c52c422a5d00"}, + {file = "matplotlib-3.9.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320edea0cadc07007765e33f878b13b3738ffa9745c5f707705692df70ffe0e0"}, + {file = "matplotlib-3.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a4a4cfc82330b27042a7169533da7991e8789d180dd5b3daeaee57d75cd5a03b"}, + {file = "matplotlib-3.9.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:37eeffeeca3c940985b80f5b9a7b95ea35671e0e7405001f249848d2b62351b6"}, + {file = "matplotlib-3.9.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3e7465ac859ee4abcb0d836137cd8414e7bb7ad330d905abced457217d4f0f45"}, + {file = "matplotlib-3.9.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4c12302c34afa0cf061bea23b331e747e5e554b0fa595c96e01c7b75bc3b858"}, + {file = "matplotlib-3.9.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b8c97917f21b75e72108b97707ba3d48f171541a74aa2a56df7a40626bafc64"}, + {file = "matplotlib-3.9.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0229803bd7e19271b03cb09f27db76c918c467aa4ce2ae168171bc67c3f508df"}, + {file = "matplotlib-3.9.4-cp313-cp313-win_amd64.whl", hash = "sha256:7c0d8ef442ebf56ff5e206f8083d08252ee738e04f3dc88ea882853a05488799"}, + {file = "matplotlib-3.9.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a04c3b00066a688834356d196136349cb32f5e1003c55ac419e91585168b88fb"}, + {file = "matplotlib-3.9.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:04c519587f6c210626741a1e9a68eefc05966ede24205db8982841826af5871a"}, + {file = "matplotlib-3.9.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308afbf1a228b8b525fcd5cec17f246bbbb63b175a3ef6eb7b4d33287ca0cf0c"}, + {file = "matplotlib-3.9.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddb3b02246ddcffd3ce98e88fed5b238bc5faff10dbbaa42090ea13241d15764"}, + {file = "matplotlib-3.9.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8a75287e9cb9eee48cb79ec1d806f75b29c0fde978cb7223a1f4c5848d696041"}, + {file = "matplotlib-3.9.4-cp313-cp313t-win_amd64.whl", hash = "sha256:488deb7af140f0ba86da003e66e10d55ff915e152c78b4b66d231638400b1965"}, + {file = "matplotlib-3.9.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3c3724d89a387ddf78ff88d2a30ca78ac2b4c89cf37f2db4bd453c34799e933c"}, + {file = "matplotlib-3.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d5f0a8430ffe23d7e32cfd86445864ccad141797f7d25b7c41759a5b5d17cfd7"}, + {file = "matplotlib-3.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bb0141a21aef3b64b633dc4d16cbd5fc538b727e4958be82a0e1c92a234160e"}, + {file = "matplotlib-3.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57aa235109e9eed52e2c2949db17da185383fa71083c00c6c143a60e07e0888c"}, + {file = "matplotlib-3.9.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b18c600061477ccfdd1e6fd050c33d8be82431700f3452b297a56d9ed7037abb"}, + {file = "matplotlib-3.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:ef5f2d1b67d2d2145ff75e10f8c008bfbf71d45137c4b648c87193e7dd053eac"}, + {file = "matplotlib-3.9.4-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:44e0ed786d769d85bc787b0606a53f2d8d2d1d3c8a2608237365e9121c1a338c"}, + {file = "matplotlib-3.9.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:09debb9ce941eb23ecdbe7eab972b1c3e0276dcf01688073faff7b0f61d6c6ca"}, + {file = "matplotlib-3.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc53cf157a657bfd03afab14774d54ba73aa84d42cfe2480c91bd94873952db"}, + {file = "matplotlib-3.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ad45da51be7ad02387801fd154ef74d942f49fe3fcd26a64c94842ba7ec0d865"}, + {file = "matplotlib-3.9.4.tar.gz", hash = "sha256:1e00e8be7393cbdc6fedfa8a6fba02cf3e83814b285db1c60b906a023ba41bc3"}, ] [package.dependencies] @@ -2672,21 +2201,24 @@ contourpy = ">=1.0.1" cycler = ">=0.10" fonttools = ">=4.22.0" importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} -kiwisolver = ">=1.0.1" -numpy = ">=1.20,<2" +kiwisolver = ">=1.3.1" +numpy = ">=1.23" packaging = ">=20.0" -pillow = ">=6.2.0" +pillow = ">=8" pyparsing = ">=2.3.1" python-dateutil = ">=2.7" +[package.extras] +dev = ["meson-python (>=0.13.1,<0.17.0)", "numpy (>=1.25)", "pybind11 (>=2.6,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7)"] + [[package]] name = "matplotlib" version = "3.10.7" description = "Python plotting package" optional = false python-versions = ">=3.10" -groups = ["examples"] -markers = "python_version >= \"3.12\"" +groups = ["main", "examples"] +markers = "python_version >= \"3.11\"" files = [ {file = "matplotlib-3.10.7-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ac81eee3b7c266dd92cee1cd658407b16c57eed08c7421fa354ed68234de380"}, {file = "matplotlib-3.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:667ecd5d8d37813a845053d8f5bf110b534c3c9f30e69ebd25d4701385935a6d"}, @@ -2759,22 +2291,6 @@ python-dateutil = ">=2.7" [package.extras] dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7)"] -[[package]] -name = "matplotlib-inline" -version = "0.1.7" -description = "Inline Matplotlib backend for Jupyter" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, - {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, -] - -[package.dependencies] -traitlets = "*" - [[package]] name = "matplotlib-inline" version = "0.2.1" @@ -2782,7 +2298,6 @@ description = "Inline Matplotlib backend for Jupyter" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76"}, {file = "matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe"}, @@ -2810,65 +2325,36 @@ files = [ typing-extensions = {version = "*", markers = "python_version < \"3.11\""} [[package]] -name = "mypy" -version = "1.14.1" -description = "Optional static typing for Python" +name = "multiprocess" +version = "0.70.18" +description = "better multiprocessing and multithreading in Python" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" +groups = ["main"] files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, + {file = "multiprocess-0.70.18-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25d4012dcaaf66b9e8e955f58482b42910c2ee526d532844d8bcf661bbc604df"}, + {file = "multiprocess-0.70.18-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:06b19433de0d02afe5869aec8931dd5c01d99074664f806c73896b0d9e527213"}, + {file = "multiprocess-0.70.18-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6fa1366f994373aaf2d4738b0f56e707caeaa05486e97a7f71ee0853823180c2"}, + {file = "multiprocess-0.70.18-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8b8940ae30139e04b076da6c5b83e9398585ebdf0f2ad3250673fef5b2ff06d6"}, + {file = "multiprocess-0.70.18-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0929ba95831adb938edbd5fb801ac45e705ecad9d100b3e653946b7716cb6bd3"}, + {file = "multiprocess-0.70.18-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4d77f8e4bfe6c6e2e661925bbf9aed4d5ade9a1c6502d5dfc10129b9d1141797"}, + {file = "multiprocess-0.70.18-pp38-pypy38_pp73-macosx_10_9_arm64.whl", hash = "sha256:2dbaae9bffa1fb2d58077c0044ffe87a8c8974e90fcf778cdf90e139c970d42a"}, + {file = "multiprocess-0.70.18-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bcac5a4e81f1554d98d1bba963eeb1bd24966432f04fcbd29b6e1a16251ad712"}, + {file = "multiprocess-0.70.18-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c0c7cd75d0987ab6166d64e654787c781dbacbcbcaaede4c1ffe664720b3e14b"}, + {file = "multiprocess-0.70.18-pp39-pypy39_pp73-macosx_10_13_arm64.whl", hash = "sha256:9fd8d662f7524a95a1be7cbea271f0b33089fe792baabec17d93103d368907da"}, + {file = "multiprocess-0.70.18-pp39-pypy39_pp73-macosx_10_13_x86_64.whl", hash = "sha256:3fbba48bfcd932747c33f0b152b26207c4e0840c35cab359afaff7a8672b1031"}, + {file = "multiprocess-0.70.18-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5f9be0342e597dde86152c10442c5fb6c07994b1c29de441b7a3a08b0e6be2a0"}, + {file = "multiprocess-0.70.18-py310-none-any.whl", hash = "sha256:60c194974c31784019c1f459d984e8f33ee48f10fcf42c309ba97b30d9bd53ea"}, + {file = "multiprocess-0.70.18-py311-none-any.whl", hash = "sha256:5aa6eef98e691281b3ad923be2832bf1c55dd2c859acd73e5ec53a66aae06a1d"}, + {file = "multiprocess-0.70.18-py312-none-any.whl", hash = "sha256:9b78f8e5024b573730bfb654783a13800c2c0f2dfc0c25e70b40d184d64adaa2"}, + {file = "multiprocess-0.70.18-py313-none-any.whl", hash = "sha256:871743755f43ef57d7910a38433cfe41319e72be1bbd90b79c7a5ac523eb9334"}, + {file = "multiprocess-0.70.18-py38-none-any.whl", hash = "sha256:dbf705e52a154fe5e90fb17b38f02556169557c2dd8bb084f2e06c2784d8279b"}, + {file = "multiprocess-0.70.18-py39-none-any.whl", hash = "sha256:e78ca805a72b1b810c690b6b4cc32579eba34f403094bbbae962b7b5bf9dfcb8"}, + {file = "multiprocess-0.70.18.tar.gz", hash = "sha256:f9597128e6b3e67b23956da07cf3d2e5cba79e2f4e0fba8d7903636663ec6d0d"}, ] [package.dependencies] -mypy_extensions = ">=1.0.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] +dill = ">=0.4.0" [[package]] name = "mypy" @@ -2877,7 +2363,6 @@ description = "Optional static typing for Python" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "mypy-1.18.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eab0cf6294dafe397c261a75f96dc2c31bffe3b944faa24db5def4e2b0f77c"}, {file = "mypy-1.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a780ca61fc239e4865968ebc5240bb3bf610ef59ac398de9a7421b54e4a207e"}, @@ -2922,6 +2407,7 @@ files = [ [package.dependencies] mypy_extensions = ">=1.0.0" pathspec = ">=0.9.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing_extensions = ">=4.6.0" [package.extras] @@ -2943,30 +2429,6 @@ files = [ {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] -[[package]] -name = "nbclient" -version = "0.10.1" -description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." -optional = false -python-versions = ">=3.8.0" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "nbclient-0.10.1-py3-none-any.whl", hash = "sha256:949019b9240d66897e442888cfb618f69ef23dc71c01cb5fced8499c2cfc084d"}, - {file = "nbclient-0.10.1.tar.gz", hash = "sha256:3e93e348ab27e712acd46fccd809139e356eb9a31aab641d1a7991a6eb4e6f68"}, -] - -[package.dependencies] -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -nbformat = ">=5.1" -traitlets = ">=5.4" - -[package.extras] -dev = ["pre-commit"] -docs = ["autodoc-traits", "flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "mock", "moto", "myst-parser", "nbconvert (>=7.0.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling", "testpath", "xmltodict"] -test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] - [[package]] name = "nbclient" version = "0.10.2" @@ -2974,7 +2436,6 @@ description = "A client library for executing notebooks. Formerly nbconvert's Ex optional = false python-versions = ">=3.9.0" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "nbclient-0.10.2-py3-none-any.whl", hash = "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d"}, {file = "nbclient-0.10.2.tar.gz", hash = "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193"}, @@ -3063,31 +2524,6 @@ files = [ {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] -[[package]] -name = "notebook" -version = "7.3.3" -description = "Jupyter Notebook - A web-based notebook environment for interactive computing" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "notebook-7.3.3-py3-none-any.whl", hash = "sha256:b193df0878956562d5171c8e25c9252b8e86c9fcc16163b8ee3fe6c5e3f422f7"}, - {file = "notebook-7.3.3.tar.gz", hash = "sha256:707a313fb882d35f921989eb3d204de942ed5132a44e4aa1fe0e8f24bb9dc25d"}, -] - -[package.dependencies] -jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.3.6,<4.4" -jupyterlab-server = ">=2.27.1,<3" -notebook-shim = ">=0.2,<0.3" -tornado = ">=6.2.0" - -[package.extras] -dev = ["hatch", "pre-commit"] -docs = ["myst-parser", "nbsphinx", "pydata-sphinx-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["importlib-resources (>=5.0) ; python_version < \"3.10\"", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.27.1,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] - [[package]] name = "notebook" version = "7.4.7" @@ -3095,7 +2531,6 @@ description = "Jupyter Notebook - A web-based notebook environment for interacti optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "notebook-7.4.7-py3-none-any.whl", hash = "sha256:362b7c95527f7dd3c4c84d410b782872fd9c734fb2524c11dd92758527b6eda6"}, {file = "notebook-7.4.7.tar.gz", hash = "sha256:3f0a04027dfcee8a876de48fba13ab77ec8c12f72f848a222ed7f5081b9e342a"}, @@ -3126,48 +2561,186 @@ files = [ ] [package.dependencies] -jupyter-server = ">=1.8,<3" - -[package.extras] -test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] +jupyter-server = ">=1.8,<3" + +[package.extras] +test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] + +[[package]] +name = "numexpr" +version = "2.10.2" +description = "Fast numerical expression evaluator for NumPy" +optional = false +python-versions = ">=3.9" +groups = ["main"] +markers = "python_version < \"3.11\"" +files = [ + {file = "numexpr-2.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5b0e82d2109c1d9e63fcd5ea177d80a11b881157ab61178ddbdebd4c561ea46"}, + {file = "numexpr-2.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc2b8035a0c2cdc352e58c3875cb668836018065cbf5752cb531015d9a568d8"}, + {file = "numexpr-2.10.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0db5ff5183935d1612653559c319922143e8fa3019007696571b13135f216458"}, + {file = "numexpr-2.10.2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15f59655458056fdb3a621b1bb8e071581ccf7e823916c7568bb7c9a3e393025"}, + {file = "numexpr-2.10.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ce8cccf944339051e44a49a124a06287fe3066d0acbff33d1aa5aee10a96abb7"}, + {file = "numexpr-2.10.2-cp310-cp310-win32.whl", hash = "sha256:ba85371c9a8d03e115f4dfb6d25dfbce05387002b9bc85016af939a1da9624f0"}, + {file = "numexpr-2.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:deb64235af9eeba59fcefa67e82fa80cfc0662e1b0aa373b7118a28da124d51d"}, + {file = "numexpr-2.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6b360eb8d392483410fe6a3d5a7144afa298c9a0aa3e9fe193e89590b47dd477"}, + {file = "numexpr-2.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d9a42f5c24880350d88933c4efee91b857c378aaea7e8b86221fff569069841e"}, + {file = "numexpr-2.10.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83fcb11988b57cc25b028a36d285287d706d1f536ebf2662ea30bd990e0de8b9"}, + {file = "numexpr-2.10.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4213a92efa9770bc28e3792134e27c7e5c7e97068bdfb8ba395baebbd12f991b"}, + {file = "numexpr-2.10.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebdbef5763ca057eea0c2b5698e4439d084a0505d9d6e94f4804f26e8890c45e"}, + {file = "numexpr-2.10.2-cp311-cp311-win32.whl", hash = "sha256:3bf01ec502d89944e49e9c1b5cc7c7085be8ca2eb9dd46a0eafd218afbdbd5f5"}, + {file = "numexpr-2.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:e2d0ae24b0728e4bc3f1d3f33310340d67321d36d6043f7ce26897f4f1042db0"}, + {file = "numexpr-2.10.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5323a46e75832334f1af86da1ef6ff0add00fbacdd266250be872b438bdf2be"}, + {file = "numexpr-2.10.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a42963bd4c62d8afa4f51e7974debfa39a048383f653544ab54f50a2f7ec6c42"}, + {file = "numexpr-2.10.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5191ba8f2975cb9703afc04ae845a929e193498c0e8bcd408ecb147b35978470"}, + {file = "numexpr-2.10.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97298b14f0105a794bea06fd9fbc5c423bd3ff4d88cbc618860b83eb7a436ad6"}, + {file = "numexpr-2.10.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9d7805ccb6be2d3b0f7f6fad3707a09ac537811e8e9964f4074d28cb35543db"}, + {file = "numexpr-2.10.2-cp312-cp312-win32.whl", hash = "sha256:cb845b2d4f9f8ef0eb1c9884f2b64780a85d3b5ae4eeb26ae2b0019f489cd35e"}, + {file = "numexpr-2.10.2-cp312-cp312-win_amd64.whl", hash = "sha256:57b59cbb5dcce4edf09cd6ce0b57ff60312479930099ca8d944c2fac896a1ead"}, + {file = "numexpr-2.10.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a37d6a51ec328c561b2ca8a2bef07025642eca995b8553a5267d0018c732976d"}, + {file = "numexpr-2.10.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:81d1dde7dd6166d8ff5727bb46ab42a6b0048db0e97ceb84a121334a404a800f"}, + {file = "numexpr-2.10.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5b3f814437d5a10797f8d89d2037cca2c9d9fa578520fc911f894edafed6ea3e"}, + {file = "numexpr-2.10.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9309f2e43fe6e4560699ef5c27d7a848b3ff38549b6b57194207cf0e88900527"}, + {file = "numexpr-2.10.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ebb73b93f5c4d6994f357fa5a47a9f7a5485577e633b3c46a603cb01445bbb19"}, + {file = "numexpr-2.10.2-cp313-cp313-win32.whl", hash = "sha256:ec04c9a3c050c175348801e27c18c68d28673b7bfb865ef88ce333be523bbc01"}, + {file = "numexpr-2.10.2-cp313-cp313-win_amd64.whl", hash = "sha256:d7a3fc83c959288544db3adc70612475d8ad53a66c69198105c74036182d10dd"}, + {file = "numexpr-2.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0495f8111c3633e265248709b8b3b521bbfa646ba384909edd10e2b9a588a83a"}, + {file = "numexpr-2.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2aa05ac71bee3b1253e73173c4d7fa96a09a18970c0226f1c2c07a71ffe988dc"}, + {file = "numexpr-2.10.2-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3a23c3002ab330056fbdd2785871937a6f2f2fa85d06c8d0ff74ea8418119d1"}, + {file = "numexpr-2.10.2-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a018a7d81326f4c73d8b5aee61794d7d8514512f43957c0db61eb2a8a86848c7"}, + {file = "numexpr-2.10.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:037859b17a0abe2b489d4c2cfdadd2bf458ec80dd83f338ea5544c7987e06b85"}, + {file = "numexpr-2.10.2-cp39-cp39-win32.whl", hash = "sha256:eb278ccda6f893a312aa0452701bb17d098b7b14eb7c9381517d509cce0a39a3"}, + {file = "numexpr-2.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:734b64c6d6a597601ce9d0ef7b666e678ec015b446f1d1412c23903c021436c3"}, + {file = "numexpr-2.10.2.tar.gz", hash = "sha256:b0aff6b48ebc99d2f54f27b5f73a58cb92fde650aeff1b397c71c8788b4fff1a"}, +] + +[package.dependencies] +numpy = ">=1.23.0" + +[[package]] +name = "numexpr" +version = "2.14.1" +description = "Fast numerical expression evaluator for NumPy" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "numexpr-2.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0fab3fd06a04f6b86102552b26aa5d85e20ac7d8296c15764c726eeabae6cc8"}, + {file = "numexpr-2.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:64ae5dfd62d74a3ef82fe0b37f80527247f3626171ad82025900f46ffca4b39a"}, + {file = "numexpr-2.14.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:955c92b064f9074d2970cf3138f5e3b965be673b82024962ed526f39bc25a920"}, + {file = "numexpr-2.14.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:75440c54fc01e130396650fdf307aa9d41a67dc06ddbfb288971b591c13a395b"}, + {file = "numexpr-2.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dde9fa47ed319e1e1728940a539df3cb78326b7754bc7c6ab3152afc91808f9b"}, + {file = "numexpr-2.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76db0bc6267e591ab9c4df405ffb533598e4c88239db7338d11ae9e4b368a85a"}, + {file = "numexpr-2.14.1-cp310-cp310-win32.whl", hash = "sha256:0d1dcbdc4d0374c0d523cee2f94f06b001623cbc1fd163612841017a3495427c"}, + {file = "numexpr-2.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:823cd82c8e7937981339f634e7a9c6a92cb2d0b9d0a5cf627a5e394fffc05377"}, + {file = "numexpr-2.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2d03fcb4644a12f70a14d74006f72662824da5b6128bf1bcd10cc3ed80e64c34"}, + {file = "numexpr-2.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2773ee1133f77009a1fc2f34fe236f3d9823779f5f75450e183137d49f00499f"}, + {file = "numexpr-2.14.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ebe4980f9494b9f94d10d2e526edc29e72516698d3bf95670ba79415492212a4"}, + {file = "numexpr-2.14.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a381e5e919a745c9503bcefffc1c7f98c972c04ec58fc8e999ed1a929e01ba6"}, + {file = "numexpr-2.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d08856cfc1b440eb1caaa60515235369654321995dd68eb9377577392020f6cb"}, + {file = "numexpr-2.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03130afa04edf83a7b590d207444f05a00363c9b9ea5d81c0f53b1ea13fad55a"}, + {file = "numexpr-2.14.1-cp311-cp311-win32.whl", hash = "sha256:db78fa0c9fcbaded3ae7453faf060bd7a18b0dc10299d7fcd02d9362be1213ed"}, + {file = "numexpr-2.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:e9b2f957798c67a2428be96b04bce85439bed05efe78eb78e4c2ca43737578e7"}, + {file = "numexpr-2.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ebae0ab18c799b0e6b8c5a8d11e1fa3848eb4011271d99848b297468a39430"}, + {file = "numexpr-2.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47041f2f7b9e69498fb311af672ba914a60e6e6d804011caacb17d66f639e659"}, + {file = "numexpr-2.14.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d686dfb2c1382d9e6e0ee0b7647f943c1886dba3adbf606c625479f35f1956c1"}, + {file = "numexpr-2.14.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eee6d4fbbbc368e6cdd0772734d6249128d957b3b8ad47a100789009f4de7083"}, + {file = "numexpr-2.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3a2839efa25f3c8d4133252ea7342d8f81226c7c4dda81f97a57e090b9d87a48"}, + {file = "numexpr-2.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9f9137f1351b310436662b5dc6f4082a245efa8950c3b0d9008028df92fefb9b"}, + {file = "numexpr-2.14.1-cp312-cp312-win32.whl", hash = "sha256:36f8d5c1bd1355df93b43d766790f9046cccfc1e32b7c6163f75bcde682cda07"}, + {file = "numexpr-2.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:fdd886f4b7dbaf167633ee396478f0d0aa58ea2f9e7ccc3c6431019623e8d68f"}, + {file = "numexpr-2.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:09078ba73cffe94745abfbcc2d81ab8b4b4e9d7bfbbde6cac2ee5dbf38eee222"}, + {file = "numexpr-2.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dce0b5a0447baa7b44bc218ec2d7dcd175b8eee6083605293349c0c1d9b82fb6"}, + {file = "numexpr-2.14.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:06855053de7a3a8425429bd996e8ae3c50b57637ad3e757e0fa0602a7874be30"}, + {file = "numexpr-2.14.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f9366d23a2e991fd5a8b5e61a17558f028ba86158a4552f8f239b005cdf83c"}, + {file = "numexpr-2.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c5f1b1605695778896534dfc6e130d54a65cd52be7ed2cd0cfee3981fd676bf5"}, + {file = "numexpr-2.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a4ba71db47ea99c659d88ee6233fa77b6dc83392f1d324e0c90ddf617ae3f421"}, + {file = "numexpr-2.14.1-cp313-cp313-win32.whl", hash = "sha256:638dce8320f4a1483d5ca4fda69f60a70ed7e66be6e68bc23fb9f1a6b78a9e3b"}, + {file = "numexpr-2.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:9fdcd4735121658a313f878fd31136d1bfc6a5b913219e7274e9fca9f8dac3bb"}, + {file = "numexpr-2.14.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:557887ad7f5d3c2a40fd7310e50597045a68e66b20a77b3f44d7bc7608523b4b"}, + {file = "numexpr-2.14.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:af111c8fe6fc55d15e4c7cab11920fc50740d913636d486545b080192cd0ad73"}, + {file = "numexpr-2.14.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33265294376e7e2ae4d264d75b798a915d2acf37b9dd2b9405e8b04f84d05cfc"}, + {file = "numexpr-2.14.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83647d846d3eeeb9a9255311236135286728b398d0d41d35dedb532dca807fe9"}, + {file = "numexpr-2.14.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6e575fd3ad41ddf3355d0c7ef6bd0168619dc1779a98fe46693cad5e95d25e6e"}, + {file = "numexpr-2.14.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:67ea4771029ce818573b1998f5ca416bd255156feea017841b86176a938f7d19"}, + {file = "numexpr-2.14.1-cp313-cp313t-win32.whl", hash = "sha256:15015d47d3d1487072d58c0e7682ef2eb608321e14099c39d52e2dd689483611"}, + {file = "numexpr-2.14.1-cp313-cp313t-win_amd64.whl", hash = "sha256:94c711f6d8f17dfb4606842b403699603aa591ab9f6bf23038b488ea9cfb0f09"}, + {file = "numexpr-2.14.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ede79f7ff06629f599081de644546ce7324f1581c09b0ac174da88a470d39c21"}, + {file = "numexpr-2.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2eac7a5a2f70b3768c67056445d1ceb4ecd9b853c8eda9563823b551aeaa5082"}, + {file = "numexpr-2.14.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5aedf38d4c0c19d3cecfe0334c3f4099fb496f54c146223d30fa930084bc8574"}, + {file = "numexpr-2.14.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439ec4d57b853792ebe5456e3160312281c3a7071ecac5532ded3278ede614de"}, + {file = "numexpr-2.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e23b87f744e04e302d82ac5e2189ae20a533566aec76a46885376e20b0645bf8"}, + {file = "numexpr-2.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:44f84e0e5af219dbb62a081606156420815890e041b87252fbcea5df55214c4c"}, + {file = "numexpr-2.14.1-cp314-cp314-win32.whl", hash = "sha256:1f1a5e817c534539351aa75d26088e9e1e0ef1b3a6ab484047618a652ccc4fc3"}, + {file = "numexpr-2.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:587c41509bc373dfb1fe6086ba55a73147297247bedb6d588cda69169fc412f2"}, + {file = "numexpr-2.14.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ec368819502b64f190c3f71be14a304780b5935c42aae5bf22c27cc2cbba70b5"}, + {file = "numexpr-2.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7e87f6d203ac57239de32261c941e9748f9309cbc0da6295eabd0c438b920d3a"}, + {file = "numexpr-2.14.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd72d8c2a165fe45ea7650b16eb8cc1792a94a722022006bb97c86fe51fd2091"}, + {file = "numexpr-2.14.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:70d80fcb418a54ca208e9a38e58ddc425c07f66485176b261d9a67c7f2864f73"}, + {file = "numexpr-2.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:edea2f20c2040df8b54ee8ca8ebda63de9545b2112872466118e9df4d0ae99f3"}, + {file = "numexpr-2.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:790447be6879a6c51b9545f79612d24c9ea0a41d537a84e15e6a8ddef0b6268e"}, + {file = "numexpr-2.14.1-cp314-cp314t-win32.whl", hash = "sha256:538961096c2300ea44240209181e31fae82759d26b51713b589332b9f2a4117e"}, + {file = "numexpr-2.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:a40b350cd45b4446076fa11843fa32bbe07024747aeddf6d467290bf9011b392"}, + {file = "numexpr-2.14.1.tar.gz", hash = "sha256:4be00b1086c7b7a5c32e31558122b7b80243fe098579b170967da83f3152b48b"}, +] + +[package.dependencies] +numpy = ">=1.23.0" [[package]] name = "numpy" -version = "1.24.4" +version = "2.0.2" description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main", "examples"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ - {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, - {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, - {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, - {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, - {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, - {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, - {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, - {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, - {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, - {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, - {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b"}, + {file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd"}, + {file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318"}, + {file = "numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8"}, + {file = "numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326"}, + {file = "numpy-2.0.2-cp310-cp310-win32.whl", hash = "sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97"}, + {file = "numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a"}, + {file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669"}, + {file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951"}, + {file = "numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9"}, + {file = "numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15"}, + {file = "numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4"}, + {file = "numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c"}, + {file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692"}, + {file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a"}, + {file = "numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c"}, + {file = "numpy-2.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded"}, + {file = "numpy-2.0.2-cp312-cp312-win32.whl", hash = "sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5"}, + {file = "numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729"}, + {file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1"}, + {file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd"}, + {file = "numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d"}, + {file = "numpy-2.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d"}, + {file = "numpy-2.0.2-cp39-cp39-win32.whl", hash = "sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa"}, + {file = "numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385"}, + {file = "numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78"}, ] [[package]] @@ -3177,7 +2750,7 @@ description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" groups = ["main", "examples"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "numpy-2.3.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e78aecd2800b32e8347ce49316d3eaf04aed849cd5b38e0af39f829a4e59f5eb"}, {file = "numpy-2.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fd09cc5d65bda1e79432859c40978010622112e9194e581e3415a3eccc7f43f"}, @@ -3274,12 +2847,112 @@ version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" -groups = ["dev", "examples"] +groups = ["main", "dev", "examples"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] +[[package]] +name = "pandas" +version = "2.3.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, + {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"}, + {file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, + {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, + {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"}, + {file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"}, + {file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"}, + {file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"}, + {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.22.4", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + [[package]] name = "pandocfilters" version = "1.5.1" @@ -3308,6 +2981,24 @@ files = [ qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["docopt", "pytest"] +[[package]] +name = "pathos" +version = "0.3.4" +description = "parallel graph management and execution in heterogeneous computing" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pathos-0.3.4-py3-none-any.whl", hash = "sha256:fe44883448c05c80d518b61df491b496f6190bb6860253f3254d8c9afb53c340"}, + {file = "pathos-0.3.4.tar.gz", hash = "sha256:bad4912d0ef865654a7cc478da65f2e1d5b69f3d92c4a7d9c9845657783c0754"}, +] + +[package.dependencies] +dill = ">=0.4.0" +multiprocess = ">=0.70.18" +pox = ">=0.3.6" +ppft = ">=1.7.7" + [[package]] name = "pathspec" version = "0.12.1" @@ -3327,7 +3018,7 @@ description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" groups = ["dev"] -markers = "python_version <= \"3.11\" and sys_platform != \"win32\" or sys_platform != \"win32\" and sys_platform != \"emscripten\"" +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\" or python_version < \"3.11\" and sys_platform != \"win32\"" files = [ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, @@ -3343,7 +3034,7 @@ description = "Tiny 'shelve'-like database with concurrency support" optional = false python-versions = "*" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, @@ -3355,8 +3046,8 @@ version = "10.4.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.8" -groups = ["examples"] -markers = "python_version <= \"3.11\"" +groups = ["main", "examples"] +markers = "python_version < \"3.11\"" files = [ {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, @@ -3454,8 +3145,8 @@ version = "12.0.0" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" -groups = ["examples"] -markers = "python_version >= \"3.12\"" +groups = ["main", "examples"] +markers = "python_version >= \"3.11\"" files = [ {file = "pillow-12.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:3adfb466bbc544b926d50fe8f4a4e6abd8c6bffd28a26177594e6e9b2b76572b"}, {file = "pillow-12.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1ac11e8ea4f611c3c0147424eae514028b5e9077dd99ab91e1bd7bc33ff145e1"}, @@ -3558,19 +3249,6 @@ test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"] tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma (>=5)", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] xmp = ["defusedxml"] -[[package]] -name = "pkgutil-resolve-name" -version = "1.3.10" -description = "Resolve a name to an object." -optional = false -python-versions = ">=3.6" -groups = ["dev"] -markers = "python_version == \"3.8\"" -files = [ - {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, - {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, -] - [[package]] name = "platformdirs" version = "4.3.6" @@ -3578,7 +3256,7 @@ description = "A small Python package for determining appropriate platform-speci optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -3596,7 +3274,7 @@ description = "A small Python package for determining appropriate platform-speci optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3"}, {file = "platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312"}, @@ -3607,23 +3285,6 @@ docs = ["furo (>=2025.9.25)", "proselint (>=0.14)", "sphinx (>=8.2.3)", "sphinx- test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.4.2)", "pytest-cov (>=7)", "pytest-mock (>=3.15.1)"] type = ["mypy (>=1.18.2)"] -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - [[package]] name = "pluggy" version = "1.6.0" @@ -3631,7 +3292,6 @@ description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -3679,20 +3339,31 @@ xlsx2csv = ["xlsx2csv (>=0.8.0)"] xlsxwriter = ["xlsxwriter"] [[package]] -name = "prometheus-client" -version = "0.21.1" -description = "Python client for the Prometheus monitoring system." +name = "pox" +version = "0.3.6" +description = "utilities for filesystem exploration and automated builds" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" +groups = ["main"] +files = [ + {file = "pox-0.3.6-py3-none-any.whl", hash = "sha256:d48654d0a3dca0c9c02dccae54a53c3870286a5217ad306b2bd94f84e008bc1b"}, + {file = "pox-0.3.6.tar.gz", hash = "sha256:84eeed39600159a62804aacfc00e353edeaae67d8c647ccaaab73a6efed3f605"}, +] + +[[package]] +name = "ppft" +version = "1.7.7" +description = "distributed and parallel Python" +optional = false +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "prometheus_client-0.21.1-py3-none-any.whl", hash = "sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301"}, - {file = "prometheus_client-0.21.1.tar.gz", hash = "sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb"}, + {file = "ppft-1.7.7-py3-none-any.whl", hash = "sha256:fb7524db110682de886b4bb5b08f7bf6a38940566074ef2f62521cbbd3864676"}, + {file = "ppft-1.7.7.tar.gz", hash = "sha256:f3f77448cfe24c2b8d2296b6d8732280b25041a3f3e1f551856c6451d3e01b96"}, ] [package.extras] -twisted = ["twisted"] +dill = ["dill (>=0.4.0)"] [[package]] name = "prometheus-client" @@ -3701,7 +3372,6 @@ description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "prometheus_client-0.23.1-py3-none-any.whl", hash = "sha256:dd1913e6e76b59cfe44e7a4b83e01afc9873c1bdfd2ed8739f1e76aeca115f99"}, {file = "prometheus_client-0.23.1.tar.gz", hash = "sha256:6ae8f9081eaaaf153a2e959d2e6c4f4fb57b12ef76c8c7980202f1e57b48b2ce"}, @@ -3765,7 +3435,7 @@ description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" groups = ["dev"] -markers = "sys_platform != \"win32\" and python_version <= \"3.11\" or sys_platform != \"win32\" and sys_platform != \"emscripten\" or os_name != \"nt\"" +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\" or os_name != \"nt\" or sys_platform != \"win32\" and python_version < \"3.11\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -3793,7 +3463,7 @@ description = "C parser in Python" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "implementation_name != \"PyPy\" or python_version <= \"3.11\"" +markers = "implementation_name != \"PyPy\"" files = [ {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"}, {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"}, @@ -3816,35 +3486,34 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyparsing" -version = "3.1.4" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" +version = "3.2.5" +description = "pyparsing - Classes and methods to define and execute parsing grammars" optional = false -python-versions = ">=3.6.8" -groups = ["examples"] -markers = "python_version <= \"3.11\"" +python-versions = ">=3.9" +groups = ["main", "examples"] files = [ - {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, - {file = "pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032"}, + {file = "pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e"}, + {file = "pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6"}, ] [package.extras] diagrams = ["jinja2", "railroad-diagrams"] [[package]] -name = "pyparsing" -version = "3.2.5" -description = "pyparsing - Classes and methods to define and execute parsing grammars" +name = "pyreadline3" +version = "3.5.4" +description = "A python implementation of GNU readline." optional = false -python-versions = ">=3.9" -groups = ["examples"] -markers = "python_version >= \"3.12\"" +python-versions = ">=3.8" +groups = ["main"] +markers = "sys_platform == \"win32\"" files = [ - {file = "pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e"}, - {file = "pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6"}, + {file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"}, + {file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"}, ] [package.extras] -diagrams = ["jinja2", "railroad-diagrams"] +dev = ["build", "flake8", "mypy", "pytest", "twine"] [[package]] name = "pytest" @@ -3875,7 +3544,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["dev", "examples"] +groups = ["main", "dev", "examples"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -3908,8 +3577,7 @@ version = "2025.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" -groups = ["dev"] -markers = "python_version == \"3.8\"" +groups = ["main"] files = [ {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, @@ -3922,7 +3590,7 @@ description = "Python for Window Extensions" optional = false python-versions = "*" groups = ["dev"] -markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\" and python_version <= \"3.11\"" +markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\" and python_version < \"3.11\"" files = [ {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, @@ -3946,23 +3614,6 @@ files = [ {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"}, ] -[[package]] -name = "pywinpty" -version = "2.0.14" -description = "Pseudo terminal support for Windows from Python." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\" and os_name == \"nt\"" -files = [ - {file = "pywinpty-2.0.14-cp310-none-win_amd64.whl", hash = "sha256:0b149c2918c7974f575ba79f5a4aad58bd859a52fa9eb1296cc22aa412aa411f"}, - {file = "pywinpty-2.0.14-cp311-none-win_amd64.whl", hash = "sha256:cf2a43ac7065b3e0dc8510f8c1f13a75fb8fde805efa3b8cff7599a1ef497bc7"}, - {file = "pywinpty-2.0.14-cp312-none-win_amd64.whl", hash = "sha256:55dad362ef3e9408ade68fd173e4f9032b3ce08f68cfe7eacb2c263ea1179737"}, - {file = "pywinpty-2.0.14-cp313-none-win_amd64.whl", hash = "sha256:074fb988a56ec79ca90ed03a896d40707131897cefb8f76f926e3834227f2819"}, - {file = "pywinpty-2.0.14-cp39-none-win_amd64.whl", hash = "sha256:5725fd56f73c0531ec218663bd8c8ff5acc43c78962fab28564871b5fce053fd"}, - {file = "pywinpty-2.0.14.tar.gz", hash = "sha256:18bd9529e4a5daf2d9719aa17788ba6013e594ae94c5a0c27e83df3278b0660e"}, -] - [[package]] name = "pywinpty" version = "3.0.2" @@ -3970,7 +3621,7 @@ description = "Pseudo terminal support for Windows from Python." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\" and os_name == \"nt\"" +markers = "os_name == \"nt\"" files = [ {file = "pywinpty-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:65db57fd3387d71e8372b6a54269cbcd0f6dfa6d4616a29e0af749ec19f5c558"}, {file = "pywinpty-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:327790d70e4c841ebd9d0f295a780177149aeb405bca44c7115a3de5c2054b23"}, @@ -4178,7 +3829,7 @@ description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, @@ -4195,7 +3846,7 @@ description = "JSON Referencing + Python" optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -4206,29 +3857,6 @@ attrs = ">=22.2.0" rpds-py = ">=0.7.0" typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} -[[package]] -name = "requests" -version = "2.32.4" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, - {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset_normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - [[package]] name = "requests" version = "2.32.5" @@ -4236,7 +3864,6 @@ description = "Python HTTP for Humans." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, @@ -4286,7 +3913,6 @@ description = "Helper functions to syntactically validate strings according to R optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f"}, {file = "rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d"}, @@ -4305,7 +3931,7 @@ description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "rpds_py-0.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a649dfd735fff086e8a9d0503a9f0c7d01b7912a333c7ae77e1515c08c146dad"}, {file = "rpds_py-0.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f16bc1334853e91ddaaa1217045dd7be166170beec337576818461268a3de67f"}, @@ -4419,7 +4045,7 @@ description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "rpds_py-0.28.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7b6013db815417eeb56b2d9d7324e64fcd4fa289caeee6e7a78b2e11fc9b438a"}, {file = "rpds_py-0.28.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a4c6b05c685c0c03f80dabaeb73e74218c49deea965ca63f76a752807397207"}, @@ -4567,43 +4193,47 @@ files = [ [[package]] name = "scipy" -version = "1.10.1" +version = "1.13.1" description = "Fundamental algorithms for scientific computing in Python" optional = false -python-versions = "<3.12,>=3.8" +python-versions = ">=3.9" groups = ["main"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ - {file = "scipy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019"}, - {file = "scipy-1.10.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2"}, - {file = "scipy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d"}, - {file = "scipy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f"}, - {file = "scipy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601"}, - {file = "scipy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea"}, - {file = "scipy-1.10.1.tar.gz", hash = "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5"}, + {file = "scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca"}, + {file = "scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f"}, + {file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989"}, + {file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f"}, + {file = "scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94"}, + {file = "scipy-1.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54"}, + {file = "scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9"}, + {file = "scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326"}, + {file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299"}, + {file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa"}, + {file = "scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59"}, + {file = "scipy-1.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b"}, + {file = "scipy-1.13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d72782f39716b2b3509cd7c33cdc08c96f2f4d2b06d51e52fb45a19ca0c86a1"}, + {file = "scipy-1.13.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:017367484ce5498445aade74b1d5ab377acdc65e27095155e448c88497755a5d"}, + {file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:949ae67db5fa78a86e8fa644b9a6b07252f449dcf74247108c50e1d20d2b4627"}, + {file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3ade0e53bc1f21358aa74ff4830235d716211d7d077e340c7349bc3542e884"}, + {file = "scipy-1.13.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ac65fb503dad64218c228e2dc2d0a0193f7904747db43014645ae139c8fad16"}, + {file = "scipy-1.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:cdd7dacfb95fea358916410ec61bbc20440f7860333aee6d882bb8046264e949"}, + {file = "scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5"}, + {file = "scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24"}, + {file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004"}, + {file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637e98dcf185ba7f8e663e122ebf908c4702420477ae52a04f9908707456ba4d"}, + {file = "scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c"}, + {file = "scipy-1.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2"}, + {file = "scipy-1.13.1.tar.gz", hash = "sha256:095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c"}, ] [package.dependencies] -numpy = ">=1.19.5,<1.27.0" +numpy = ">=1.22.4,<2.3" [package.extras] -dev = ["click", "doit (>=0.36.0)", "flake8", "mypy", "pycodestyle", "pydevtool", "rich-click", "typing_extensions"] -doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] -test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.12.0)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0)", "sphinx-design (>=0.4.0)"] +test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] [[package]] name = "scipy" @@ -4612,7 +4242,7 @@ description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.11" groups = ["main"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "scipy-1.16.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97"}, {file = "scipy-1.16.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:8be1ca9170fcb6223cc7c27f4305d680ded114a1567c0bd2bfcbf947d1b17511"}, @@ -4702,28 +4332,6 @@ nativelib = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\"", "pywin32 ; s objc = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\""] win32 = ["pywin32 ; sys_platform == \"win32\""] -[[package]] -name = "setuptools" -version = "75.3.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "setuptools-75.3.2-py3-none-any.whl", hash = "sha256:90ab613b6583fc02d5369cbca13ea26ea0e182d1df2d943ee9cbe81d4c61add9"}, - {file = "setuptools-75.3.2.tar.gz", hash = "sha256:3c1383e1038b68556a382c1e8ded8887cd20141b0eb5708a6c8d277de49364f5"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.5.2) ; sys_platform != \"cygwin\""] -core = ["importlib-metadata (>=6) ; python_version < \"3.10\"", "importlib-resources (>=5.10.2) ; python_version < \"3.9\"", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "ruff (<=0.7.1)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.12.*)", "pytest-mypy"] - [[package]] name = "setuptools" version = "80.9.0" @@ -4731,7 +4339,6 @@ description = "Easily download, build, install, upgrade, and uninstall Python pa optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, @@ -4746,13 +4353,148 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] +[[package]] +name = "shapely" +version = "2.0.7" +description = "Manipulation and analysis of geometric objects" +optional = false +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version < \"3.11\"" +files = [ + {file = "shapely-2.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:33fb10e50b16113714ae40adccf7670379e9ccf5b7a41d0002046ba2b8f0f691"}, + {file = "shapely-2.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f44eda8bd7a4bccb0f281264b34bf3518d8c4c9a8ffe69a1a05dabf6e8461147"}, + {file = "shapely-2.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf6c50cd879831955ac47af9c907ce0310245f9d162e298703f82e1785e38c98"}, + {file = "shapely-2.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04a65d882456e13c8b417562c36324c0cd1e5915f3c18ad516bb32ee3f5fc895"}, + {file = "shapely-2.0.7-cp310-cp310-win32.whl", hash = "sha256:7e97104d28e60b69f9b6a957c4d3a2a893b27525bc1fc96b47b3ccef46726bf2"}, + {file = "shapely-2.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:35524cc8d40ee4752520819f9894b9f28ba339a42d4922e92c99b148bed3be39"}, + {file = "shapely-2.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5cf23400cb25deccf48c56a7cdda8197ae66c0e9097fcdd122ac2007e320bc34"}, + {file = "shapely-2.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8f1da01c04527f7da59ee3755d8ee112cd8967c15fab9e43bba936b81e2a013"}, + {file = "shapely-2.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f623b64bb219d62014781120f47499a7adc30cf7787e24b659e56651ceebcb0"}, + {file = "shapely-2.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6d95703efaa64aaabf278ced641b888fc23d9c6dd71f8215091afd8a26a66e3"}, + {file = "shapely-2.0.7-cp311-cp311-win32.whl", hash = "sha256:2f6e4759cf680a0f00a54234902415f2fa5fe02f6b05546c662654001f0793a2"}, + {file = "shapely-2.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:b52f3ab845d32dfd20afba86675c91919a622f4627182daec64974db9b0b4608"}, + {file = "shapely-2.0.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4c2b9859424facbafa54f4a19b625a752ff958ab49e01bc695f254f7db1835fa"}, + {file = "shapely-2.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5aed1c6764f51011d69a679fdf6b57e691371ae49ebe28c3edb5486537ffbd51"}, + {file = "shapely-2.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73c9ae8cf443187d784d57202199bf9fd2d4bb7d5521fe8926ba40db1bc33e8e"}, + {file = "shapely-2.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9469f49ff873ef566864cb3516091881f217b5d231c8164f7883990eec88b73"}, + {file = "shapely-2.0.7-cp312-cp312-win32.whl", hash = "sha256:6bca5095e86be9d4ef3cb52d56bdd66df63ff111d580855cb8546f06c3c907cd"}, + {file = "shapely-2.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:f86e2c0259fe598c4532acfcf638c1f520fa77c1275912bbc958faecbf00b108"}, + {file = "shapely-2.0.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a0c09e3e02f948631c7763b4fd3dd175bc45303a0ae04b000856dedebefe13cb"}, + {file = "shapely-2.0.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:06ff6020949b44baa8fc2e5e57e0f3d09486cd5c33b47d669f847c54136e7027"}, + {file = "shapely-2.0.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6dbf096f961ca6bec5640e22e65ccdec11e676344e8157fe7d636e7904fd36"}, + {file = "shapely-2.0.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adeddfb1e22c20548e840403e5e0b3d9dc3daf66f05fa59f1fcf5b5f664f0e98"}, + {file = "shapely-2.0.7-cp313-cp313-win32.whl", hash = "sha256:a7f04691ce1c7ed974c2f8b34a1fe4c3c5dfe33128eae886aa32d730f1ec1913"}, + {file = "shapely-2.0.7-cp313-cp313-win_amd64.whl", hash = "sha256:aaaf5f7e6cc234c1793f2a2760da464b604584fb58c6b6d7d94144fd2692d67e"}, + {file = "shapely-2.0.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19cbc8808efe87a71150e785b71d8a0e614751464e21fb679d97e274eca7bd43"}, + {file = "shapely-2.0.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc19b78cc966db195024d8011649b4e22812f805dd49264323980715ab80accc"}, + {file = "shapely-2.0.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd37d65519b3f8ed8976fa4302a2827cbb96e0a461a2e504db583b08a22f0b98"}, + {file = "shapely-2.0.7-cp37-cp37m-win32.whl", hash = "sha256:25085a30a2462cee4e850a6e3fb37431cbbe4ad51cbcc163af0cea1eaa9eb96d"}, + {file = "shapely-2.0.7-cp37-cp37m-win_amd64.whl", hash = "sha256:1a2e03277128e62f9a49a58eb7eb813fa9b343925fca5e7d631d50f4c0e8e0b8"}, + {file = "shapely-2.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e1c4f1071fe9c09af077a69b6c75f17feb473caeea0c3579b3e94834efcbdc36"}, + {file = "shapely-2.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3697bd078b4459f5a1781015854ef5ea5d824dbf95282d0b60bfad6ff83ec8dc"}, + {file = "shapely-2.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e9fed9a7d6451979d914cb6ebbb218b4b4e77c0d50da23e23d8327948662611"}, + {file = "shapely-2.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2934834c7f417aeb7cba3b0d9b4441a76ebcecf9ea6e80b455c33c7c62d96a24"}, + {file = "shapely-2.0.7-cp38-cp38-win32.whl", hash = "sha256:2e4a1749ad64bc6e7668c8f2f9479029f079991f4ae3cb9e6b25440e35a4b532"}, + {file = "shapely-2.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:8ae5cb6b645ac3fba34ad84b32fbdccb2ab321facb461954925bde807a0d3b74"}, + {file = "shapely-2.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4abeb44b3b946236e4e1a1b3d2a0987fb4d8a63bfb3fdefb8a19d142b72001e5"}, + {file = "shapely-2.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cd0e75d9124b73e06a42bf1615ad3d7d805f66871aa94538c3a9b7871d620013"}, + {file = "shapely-2.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7977d8a39c4cf0e06247cd2dca695ad4e020b81981d4c82152c996346cf1094b"}, + {file = "shapely-2.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0145387565fcf8f7c028b073c802956431308da933ef41d08b1693de49990d27"}, + {file = "shapely-2.0.7-cp39-cp39-win32.whl", hash = "sha256:98697c842d5c221408ba8aa573d4f49caef4831e9bc6b6e785ce38aca42d1999"}, + {file = "shapely-2.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:a3fb7fbae257e1b042f440289ee7235d03f433ea880e73e687f108d044b24db5"}, + {file = "shapely-2.0.7.tar.gz", hash = "sha256:28fe2997aab9a9dc026dc6a355d04e85841546b2a5d232ed953e3321ab958ee5"}, +] + +[package.dependencies] +numpy = ">=1.14,<3" + +[package.extras] +docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "shapely" +version = "2.1.2" +description = "Manipulation and analysis of geometric objects" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "shapely-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7ae48c236c0324b4e139bea88a306a04ca630f49be66741b340729d380d8f52f"}, + {file = "shapely-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eba6710407f1daa8e7602c347dfc94adc02205ec27ed956346190d66579eb9ea"}, + {file = "shapely-2.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef4a456cc8b7b3d50ccec29642aa4aeda959e9da2fe9540a92754770d5f0cf1f"}, + {file = "shapely-2.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e38a190442aacc67ff9f75ce60aec04893041f16f97d242209106d502486a142"}, + {file = "shapely-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:40d784101f5d06a1fd30b55fc11ea58a61be23f930d934d86f19a180909908a4"}, + {file = "shapely-2.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f6f6cd5819c50d9bcf921882784586aab34a4bd53e7553e175dece6db513a6f0"}, + {file = "shapely-2.1.2-cp310-cp310-win32.whl", hash = "sha256:fe9627c39c59e553c90f5bc3128252cb85dc3b3be8189710666d2f8bc3a5503e"}, + {file = "shapely-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:1d0bfb4b8f661b3b4ec3565fa36c340bfb1cda82087199711f86a88647d26b2f"}, + {file = "shapely-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91121757b0a36c9aac3427a651a7e6567110a4a67c97edf04f8d55d4765f6618"}, + {file = "shapely-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:16a9c722ba774cf50b5d4541242b4cce05aafd44a015290c82ba8a16931ff63d"}, + {file = "shapely-2.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cc4f7397459b12c0b196c9efe1f9d7e92463cbba142632b4cc6d8bbbbd3e2b09"}, + {file = "shapely-2.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:136ab87b17e733e22f0961504d05e77e7be8c9b5a8184f685b4a91a84efe3c26"}, + {file = "shapely-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:16c5d0fc45d3aa0a69074979f4f1928ca2734fb2e0dde8af9611e134e46774e7"}, + {file = "shapely-2.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6ddc759f72b5b2b0f54a7e7cde44acef680a55019eb52ac63a7af2cf17cb9cd2"}, + {file = "shapely-2.1.2-cp311-cp311-win32.whl", hash = "sha256:2fa78b49485391224755a856ed3b3bd91c8455f6121fee0db0e71cefb07d0ef6"}, + {file = "shapely-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:c64d5c97b2f47e3cd9b712eaced3b061f2b71234b3fc263e0fcf7d889c6559dc"}, + {file = "shapely-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe2533caae6a91a543dec62e8360fe86ffcdc42a7c55f9dfd0128a977a896b94"}, + {file = "shapely-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ba4d1333cc0bc94381d6d4308d2e4e008e0bd128bdcff5573199742ee3634359"}, + {file = "shapely-2.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0bd308103340030feef6c111d3eb98d50dc13feea33affc8a6f9fa549e9458a3"}, + {file = "shapely-2.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e7d4d7ad262a48bb44277ca12c7c78cb1b0f56b32c10734ec9a1d30c0b0c54b"}, + {file = "shapely-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9eddfe513096a71896441a7c37db72da0687b34752c4e193577a145c71736fc"}, + {file = "shapely-2.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:980c777c612514c0cf99bc8a9de6d286f5e186dcaf9091252fcd444e5638193d"}, + {file = "shapely-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9111274b88e4d7b54a95218e243282709b330ef52b7b86bc6aaf4f805306f454"}, + {file = "shapely-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:743044b4cfb34f9a67205cee9279feaf60ba7d02e69febc2afc609047cb49179"}, + {file = "shapely-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8"}, + {file = "shapely-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a"}, + {file = "shapely-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e"}, + {file = "shapely-2.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6"}, + {file = "shapely-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af"}, + {file = "shapely-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd"}, + {file = "shapely-2.1.2-cp313-cp313-win32.whl", hash = "sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350"}, + {file = "shapely-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715"}, + {file = "shapely-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40"}, + {file = "shapely-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b"}, + {file = "shapely-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801"}, + {file = "shapely-2.1.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0"}, + {file = "shapely-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c"}, + {file = "shapely-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99"}, + {file = "shapely-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf"}, + {file = "shapely-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c"}, + {file = "shapely-2.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:9a522f460d28e2bf4e12396240a5fc1518788b2fcd73535166d748399ef0c223"}, + {file = "shapely-2.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ff629e00818033b8d71139565527ced7d776c269a49bd78c9df84e8f852190c"}, + {file = "shapely-2.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f67b34271dedc3c653eba4e3d7111aa421d5be9b4c4c7d38d30907f796cb30df"}, + {file = "shapely-2.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21952dc00df38a2c28375659b07a3979d22641aeb104751e769c3ee825aadecf"}, + {file = "shapely-2.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1f2f33f486777456586948e333a56ae21f35ae273be99255a191f5c1fa302eb4"}, + {file = "shapely-2.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cf831a13e0d5a7eb519e96f58ec26e049b1fad411fc6fc23b162a7ce04d9cffc"}, + {file = "shapely-2.1.2-cp314-cp314-win32.whl", hash = "sha256:61edcd8d0d17dd99075d320a1dd39c0cb9616f7572f10ef91b4b5b00c4aeb566"}, + {file = "shapely-2.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:a444e7afccdb0999e203b976adb37ea633725333e5b119ad40b1ca291ecf311c"}, + {file = "shapely-2.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5ebe3f84c6112ad3d4632b1fd2290665aa75d4cef5f6c5d77c4c95b324527c6a"}, + {file = "shapely-2.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5860eb9f00a1d49ebb14e881f5caf6c2cf472c7fd38bd7f253bbd34f934eb076"}, + {file = "shapely-2.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b705c99c76695702656327b819c9660768ec33f5ce01fa32b2af62b56ba400a1"}, + {file = "shapely-2.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a1fd0ea855b2cf7c9cddaf25543e914dd75af9de08785f20ca3085f2c9ca60b0"}, + {file = "shapely-2.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:df90e2db118c3671a0754f38e36802db75fe0920d211a27481daf50a711fdf26"}, + {file = "shapely-2.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:361b6d45030b4ac64ddd0a26046906c8202eb60d0f9f53085f5179f1d23021a0"}, + {file = "shapely-2.1.2-cp314-cp314t-win32.whl", hash = "sha256:b54df60f1fbdecc8ebc2c5b11870461a6417b3d617f555e5033f1505d36e5735"}, + {file = "shapely-2.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9"}, + {file = "shapely-2.1.2.tar.gz", hash = "sha256:2ed4ecb28320a433db18a5bf029986aa8afcfd740745e78847e330d5d94922a9"}, +] + +[package.dependencies] +numpy = ">=1.21" + +[package.extras] +docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] +test = ["pytest", "pytest-cov", "scipy-doctest"] + [[package]] name = "six" version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["dev", "examples"] +groups = ["main", "dev", "examples"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -4770,19 +4512,6 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] -[[package]] -name = "soupsieve" -version = "2.7" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, - {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, -] - [[package]] name = "soupsieve" version = "2.8" @@ -4790,7 +4519,6 @@ description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c"}, {file = "soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f"}, @@ -4845,7 +4573,7 @@ description = "A tiny CSS parser" optional = false python-versions = ">=3.7" groups = ["dev"] -markers = "python_version <= \"3.11\"" +markers = "python_version < \"3.11\"" files = [ {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, @@ -4865,7 +4593,7 @@ description = "A tiny CSS parser" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version >= \"3.12\"" +markers = "python_version >= \"3.11\"" files = [ {file = "tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"}, {file = "tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"}, @@ -4878,19 +4606,6 @@ webencodings = ">=0.4" doc = ["sphinx", "sphinx_rtd_theme"] test = ["pytest", "ruff"] -[[package]] -name = "tokenize-rt" -version = "6.0.0" -description = "A wrapper around the stdlib `tokenize` which roundtrips." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "tokenize_rt-6.0.0-py2.py3-none-any.whl", hash = "sha256:d4ff7ded2873512938b4f8cbb98c9b07118f01d30ac585a30d7a88353ca36d22"}, - {file = "tokenize_rt-6.0.0.tar.gz", hash = "sha256:b9711bdfc51210211137499b5e355d3de5ec88a85d2025c520cbb921b5194367"}, -] - [[package]] name = "tokenize-rt" version = "6.2.0" @@ -4898,7 +4613,6 @@ description = "A wrapper around the stdlib `tokenize` which roundtrips." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "tokenize_rt-6.2.0-py2.py3-none-any.whl", hash = "sha256:a152bf4f249c847a66497a4a95f63376ed68ac6abf092a2f7cfb29d044ecff44"}, {file = "tokenize_rt-6.2.0.tar.gz", hash = "sha256:8439c042b330c553fdbe1758e4a05c0ed460dbbbb24a606f11f0dee75da4cad6"}, @@ -4957,28 +4671,6 @@ files = [ {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"}, ] -[[package]] -name = "tornado" -version = "6.4.2" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1"}, - {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803"}, - {file = "tornado-6.4.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec"}, - {file = "tornado-6.4.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946"}, - {file = "tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf"}, - {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634"}, - {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73"}, - {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c"}, - {file = "tornado-6.4.2-cp38-abi3-win32.whl", hash = "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482"}, - {file = "tornado-6.4.2-cp38-abi3-win_amd64.whl", hash = "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38"}, - {file = "tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b"}, -] - [[package]] name = "tornado" version = "6.5.2" @@ -4986,7 +4678,6 @@ description = "Tornado is a Python web framework and asynchronous networking lib optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2436822940d37cde62771cff8774f4f00b3c8024fe482e16ca8387b8a2724db6"}, {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:583a52c7aa94ee046854ba81d9ebb6c81ec0fd30386d96f7640c96dad45a03ef"}, @@ -5040,19 +4731,6 @@ files = [ docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - [[package]] name = "typing-extensions" version = "4.15.0" @@ -5060,7 +4738,6 @@ description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, @@ -5072,8 +4749,7 @@ version = "2025.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" -groups = ["dev"] -markers = "python_version >= \"3.9\"" +groups = ["main", "dev"] files = [ {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, @@ -5122,25 +4798,6 @@ files = [ [package.extras] dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] -[[package]] -name = "urllib3" -version = "2.2.3" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - [[package]] name = "urllib3" version = "2.5.0" @@ -5148,7 +4805,6 @@ description = "HTTP library with thread-safe connection pooling, file post, and optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, @@ -5172,23 +4828,6 @@ files = [ {file = "wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605"}, ] -[[package]] -name = "webcolors" -version = "24.8.0" -description = "A library for working with the color formats defined by HTML and CSS." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "webcolors-24.8.0-py3-none-any.whl", hash = "sha256:fc4c3b59358ada164552084a8ebee637c221e4059267d0f8325b3b560f6c7f0a"}, - {file = "webcolors-24.8.0.tar.gz", hash = "sha256:08b07af286a01bcd30d583a7acadf629583d1f79bfef27dd2c2c5c263817277d"}, -] - -[package.extras] -docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] -tests = ["coverage[toml]"] - [[package]] name = "webcolors" version = "24.11.1" @@ -5196,7 +4835,6 @@ description = "A library for working with the color formats defined by HTML and optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "webcolors-24.11.1-py3-none-any.whl", hash = "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9"}, {file = "webcolors-24.11.1.tar.gz", hash = "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6"}, @@ -5214,24 +4852,6 @@ files = [ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] -[[package]] -name = "websocket-client" -version = "1.8.0" -description = "WebSocket client for Python with low level API options" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" -files = [ - {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, - {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, -] - -[package.extras] -docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] -optional = ["python-socks", "wsaccel"] -test = ["websockets"] - [[package]] name = "websocket-client" version = "1.9.0" @@ -5239,7 +4859,6 @@ description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.12\"" files = [ {file = "websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef"}, {file = "websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98"}, @@ -5268,8 +4887,8 @@ version = "3.20.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" -groups = ["dev", "examples"] -markers = "python_version < \"3.10\"" +groups = ["main", "dev", "examples"] +markers = "python_version == \"3.9\"" files = [ {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, @@ -5285,5 +4904,5 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" -python-versions = "^3.8" -content-hash = "17b60b7f0f84b1543ebe4b7a60a1d2f82c598c22c88d20bcce764e657d644611" +python-versions = "^3.9" +content-hash = "4a2f0b1c5894aa64fd619bb5d21363a7895b6ed5f38683efd03c91db167555f4" diff --git a/pyproject.toml b/pyproject.toml index efbf767..6c722a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,11 +7,12 @@ readme = "README.md" packages = [{ include = "MITRotor" }] [tool.poetry.dependencies] -python = "^3.8" +python = "^3.9" numpy = ">=1.16.5" scipy = ">=1.6" unified-momentum-model = {git = "https://github.com/Howland-Lab/Unified-Momentum-Model.git"} pyyaml = "^6.0.1" +floris = "^4.5.1" [tool.poetry.group.dev.dependencies] black = { extras = ["jupyter"], version = "^23.9.1" } From 4253147792b7919a99c53dec46dfed32c0ac9ac9 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Mon, 22 Dec 2025 15:41:01 -0500 Subject: [PATCH 02/50] First attempt with saving bem solutions --- MITRotor/FlorisInterface.py | 77 ------------ MITRotor/FlorisInterface/FlorisInterface.py | 101 +++++++++++++++ examples/example_05_floris_integration.ipynb | 124 +++++++++++++++++++ 3 files changed, 225 insertions(+), 77 deletions(-) delete mode 100644 MITRotor/FlorisInterface.py create mode 100644 MITRotor/FlorisInterface/FlorisInterface.py create mode 100644 examples/example_05_floris_integration.ipynb diff --git a/MITRotor/FlorisInterface.py b/MITRotor/FlorisInterface.py deleted file mode 100644 index 54da501..0000000 --- a/MITRotor/FlorisInterface.py +++ /dev/null @@ -1,77 +0,0 @@ -import numpy as np -from attrs import define, field -from typing import Literal -# FLORIS Imports -from floris.type_dec import floris_float_type, NDArrayFloat -from floris.core.turbine.operation_models import BaseOperationModel -# MITRotor Imports -from MITRotor.ReferenceTurbines import IEA15MW -from MITRotor.RotorDefinition import RotorDefinition -from MITRotor.Geometry import BEMGeometry -from MITRotor.Momentum import UnifiedMomentum -from MITRotor.BEMSolver import BEM, BEMSolution - -@define -class MITRotorTurbine(BaseOperationModel): - """ - A turbine operation model that calls MITRotor. - """ - # user can define a BEM model if they want a different rotor, momentum model, or geometry - default_bem = BEM( - rotor=IEA15MW(), - momentum_model = UnifiedMomentum(averaging = "rotor"), - geometry = BEMGeometry(Nr = 10, Ntheta = 20), - ) - bem_model = field(init = False, default = default_bem, type = BEM) - # save most recent solution by unique floris arguments - _bem_solution: BEMSolution = field(init=False, default=None) - _last_key: bytes = field(init=False, default=None) - - def _get_solution_key(self, velocities: np.ndarray) -> bytes: # TODO: add more inputs - # Fast, deterministic, and explicit - return velocities.tobytes() - - def _get_solution(self, - power_thrust_table, - velocities, - air_density=None, - ): - # create cache key for current inputs - key = self._velocity_key(velocities) # TODO: add more inputs - # update solution if conditions are different - if key != self._last_key: - self._bem_solution = self.bem_model( # TODO: make sure these inputs are right - power_thrust_table, - velocities, - air_density, - ) - self._last_key = key - return self._bem_solution - - def power( - self, - velocities: NDArrayFloat, - turbulence_intensities: NDArrayFloat, - yaw_angles: NDArrayFloat, - tilt_angles: NDArrayFloat, - **_ - ) -> NDArrayFloat: - return self._get_solution( - power_thrust_table, velocities, air_density - ).power - - - def thrust_coefficient( - self, - velocities: NDArrayFloat, - **_ - ) -> NDArrayFloat: - return self._get_solution(power_thrust_table, velocities, air_density).power - - - def axial_induction( - self, - velocities: NDArrayFloat, - **_ - ) -> NDArrayFloat: - return self._get_solution(power_thrust_table, velocities, air_density).power \ No newline at end of file diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py new file mode 100644 index 0000000..b04e131 --- /dev/null +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -0,0 +1,101 @@ +import numpy as np +from attrs import define, field +from typing import Literal, Optional +from scipy.interpolate import interp1d +# FLORIS Imports +from floris.type_dec import floris_float_type, NDArrayFloat +from floris.core.turbine.operation_models import BaseOperationModel +from floris.core.rotor_velocity import average_velocity +# MITRotor Imports +from MITRotor.ReferenceTurbines import IEA15MW +from MITRotor.Momentum import UnifiedMomentum +from MITRotor.Geometry import BEMGeometry +from MITRotor.BEMSolver import BEM, BEMSolution + +def csv_to_interp(csv_file): + # read in csv + data = np.loadtxt(csv_file, delimiter=",", skiprows=1) + # split data into x (wind speed) and y (either pitch or tsr) + x = data[:, 0] + y = data[:, 1] + # sort by x (wind speed) + idx = np.argsort(x) + x = x[idx] + y = y[idx] + # return interpolator for y + return interp1d(x, y, kind="linear", bounds_error=False, fill_value="extrapolate") + +@define +class MITRotorTurbine(BaseOperationModel): + """ + A turbine operation model that calls MITRotor. + """ + # user can define a BEM model if they want a different rotor, momentum model, or geometry + default_bem = BEM( + rotor=IEA15MW(), + momentum_model = UnifiedMomentum(averaging = "rotor"), + geometry = BEMGeometry(Nr = 10, Ntheta = 20), + ) + bem_model = field(init = False, default = default_bem, type = BEM) + # save most recent solution by unique floris arguments + _bem_sol = field(init=False, default=None, type = Optional[list[BEMSolution]]) + _avg_vels = field(init=False, default=None, type = Optional[NDArrayFloat]) + _last_key = field(init=False, default=None, type = bytes) + # save blade pitch and tsr interpolation objects + # TODO -> figure out how to make csv change with rotor type + _pitch_interp = field(init = False, default = csv_to_interp("pitch_15mw.csv")) + _tsr_interp = field(init = False, default= csv_to_interp("tsr_15mw.csv")) + + def _get_solution_key(self, velocities: np.ndarray) -> bytes: # TODO: add more inputs + # Fast, deterministic, and explicit + return velocities.tobytes() + + def _get_solutions(self, + velocities: NDArrayFloat, + yaw_angles: NDArrayFloat, + tilt_angles: NDArrayFloat, + ): + n_findex, n_turbines = yaw_angles.shape + # create cache key for current inputs + key = self._get_solution_key(velocities) # TODO: add more inputs + # update solution if conditions are different + if key != self._last_key: + self._bem_sol = [None] * n_findex + self._avg_vels = np.empty((n_findex, n_turbines), dtype=velocities.dtype) + self._last_key = key + # loop over flow conditions + for findex in range(n_findex): + cond_vels, cond_yaws, cond_tilts = velocities[findex], yaw_angles[findex], tilt_angles[findex] + rotor_avg_vels = average_velocity(cond_vels, method="cubic-mean") # TODO: does method need to be user input? + pitch_vals = self._pitch_interp(rotor_avg_vels) + tsr_vals = self._tsr_interp(rotor_avg_vels) + self._bem_sol[findex] = self.bem_model(pitch_vals, tsr_vals, yaw = cond_yaws, tilt = cond_tilts) + self._avg_vels[findex] = rotor_avg_vels + + return self._bem_sol + + def power(self, + velocities: NDArrayFloat, + yaw_angles: NDArrayFloat, + tilt_angles: NDArrayFloat, + **_ + ) -> NDArrayFloat: + return self._get_solutions(velocities, yaw_angles, tilt_angles).Cp() # TODO: what type of averaging do we want? AND make into POWER + + + def thrust_coefficient(self, + velocities: NDArrayFloat, + yaw_angles: NDArrayFloat, + tilt_angles: NDArrayFloat, + **_ + ) -> NDArrayFloat: + return self._get_solutions(velocities, yaw_angles, tilt_angles).Ct() # TODO: what type of averaging do we want? + + + def axial_induction(self, + velocities: NDArrayFloat, + yaw_angles: NDArrayFloat, + tilt_angles: NDArrayFloat, + **_ + ) -> NDArrayFloat: + return self._get_solutions(velocities, yaw_angles, tilt_angles).a() # TODO: what type of averaging do we want? \ No newline at end of file diff --git a/examples/example_05_floris_integration.ipynb b/examples/example_05_floris_integration.ipynb new file mode 100644 index 0000000..5cafc1b --- /dev/null +++ b/examples/example_05_floris_integration.ipynb @@ -0,0 +1,124 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 26, + "id": "eb249327", + "metadata": {}, + "outputs": [], + "source": [ + "from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "9cc53ad8", + "metadata": {}, + "outputs": [], + "source": [ + "def check_interp(tsr_csv, pitch_csv):\n", + " tsr_interp = csv_to_interp(tsr_csv)\n", + " pitch_interp = csv_to_interp(pitch_csv)\n", + " print(type(pitch_interp))\n", + " # interp values\n", + " x_interp_vals = np.linspace(0, 25, num=100)\n", + " tsr_interp_vals = tsr_interp(x_interp_vals)\n", + " pitch_interp_vals = pitch_interp(x_interp_vals)\n", + " # actual values\n", + " tsr_data = np.loadtxt(tsr_csv, delimiter=\",\", skiprows=1)\n", + " pitch_data = np.loadtxt(pitch_csv, delimiter=\",\", skiprows=1)\n", + " # plot\n", + " plt.plot(x_interp_vals, tsr_interp_vals, label = \"TSR Interpolation\")\n", + " plt.plot(x_interp_vals, pitch_interp_vals, label = \"Pitch Interpolation\")\n", + " plt.scatter(tsr_data[:, 0], tsr_data[:, 1], label = \"TSR Data\")\n", + " plt.scatter(pitch_data[:, 0], pitch_data[:, 1], label = \"Pitch Data\")\n", + " plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "08c83a7f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAAGdCAYAAACyzRGfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAXh5JREFUeJzt3Qd4k2XXB/B/926hFFoKpey9FNlDZMtw4UJFUMRPRBQBUV4n+irugQOVVwUHDlCQoaAM2UNGGTKkCLLaQoEOWjpo813nTlOSNmmTNDv/33XlSpM8SZ4+DTwn933OuX00Go0GRERERA7i66g3IiIiImLwQURERA7HkQ8iIiJyKAYfRERE5FAMPoiIiMihGHwQERGRQzH4ICIiIodi8EFEREQO5Q8XU1xcjNOnTyMiIgI+Pj7O3h0iIiIyg/Qszc7ORnx8PHx9fd0r+JDAIyEhwdm7QURERFY4ceIE6tat617Bh4x46HY+MjLS2btDREREZsjKylKDB7rzuFsFH7qpFgk8GHwQERG5F3NSJphwSkRERA7F4IOIiIgcisEHEREROZTL5XwQEXlDSeLly5dRVFTk7F0hskhAQAD8/PxQVQw+iIgcqKCgACkpKcjNzeVxJ7dMJpUy2vDw8Cq9DoMPIiIHNlE8evSo+uYojZgCAwPZTJHcasTu7NmzOHnyJJo0aVKlERAGH0REDhz1kABEeiGEhobyuJPbqVmzJo4dO4bCwsIqBR9MOCUicrDKWk8TuSpbLXvCfwFERETkUFUKPl599VUVBU2cOLH0vry8PIwfPx41atRQCSnDhw9HWlqaLfaViIjIbY0ePRo33XSTy7yOWwYff/75Jz755BO0bdvW4P7HH38cS5Yswfz587F27Vq1UNwtt9xii30lIiInkC+ZFV1eeOEFtd3ChQvRpUsXREVFqfU9WrVqZfDldM6cOaXPkamn2rVr44477sDx48crfH95XrVq1Sza5969exu8tzs6duyYOlZJSUkG97/33nvqmHhd8HHx4kXcfffdmD17NqpXr156f2ZmJj777DO8/fbb6NOnDzp06IAvvvgCmzZtwpYtW2y530RE5CBSGqy7vPvuu2rdLf37pkyZglWrVqlAQka7t23bhh07duDll19WiYn6dM89deoUfvzxRxw6dAi33XabSycJu5qoqCiLgzGPCD5kWmXIkCHo16+fwf3yYZMPmv79zZs3R7169bB582ajr5Wfn69WwtO/2ENqZh7eW3kYr/560C6vT0TkqeLi4kovcuKTb+P698kUu4x4d+/eHU888QSaNWuGpk2bqqmBDz/80OC1dM+VUY9u3bphzJgxKlix5P9+GWlp3749vvrqK9SvX1/t05133ons7OzSaQkZeZcRAt1Ii4wiiH379uH6669X+xwbG4uRI0ciPT3dYMTkkUceUaMmMTExGDhwYOl+z5o1Sz03JCQEDRs2xIIFCwz2a+/eveqLtzwuqQcPPvig+rJuyvLly9GjRw8VSMj2Q4cOxZEjR0ofb9Cggbq+6qqr1PvLvhmbdpHz6KOPPopatWohODhYvabMTuj88ccf6vkSIF5zzTWq0kqOvQR+bhN8fPfdd9i5cydmzJhR7rHU1FRVt142IpM/sDxmjLyOfHB0FylBs4ez2fl4Z+XfmLvpGHILLtvlPYiIrOmdIP8nOfoi72tLElD89ddf6uRurjNnzqipGinZtLRsU07SixYtwtKlS9VFgg3JQxQSdHTt2hVjx44tHZ2Rc0tGRoYKDuRkvn37dnXyl5zE22+/3eC1586dq85lGzduxMcff1x6/7PPPqtGdnbv3q1G/yXgOXDggHosJydHBSoyGyAnfkk9WLlypQpkTMnJycGkSZPUvkhgIFNRN998syrHFhKUCXkd+R1++ukno68zdepUNYok+y3n58aNG6t9OX/+vMF2Tz/9NN566y31fv7+/rj//vvhLBb1+Thx4gQee+wx/P777yq6soVp06apg68j0a89ApDWdSKREB2CE+cvYc3BsxjStrbN34OIyFKXCovQ8rkVDj9w+18ciNBA27V6mjBhAtavX482bdogMTFR5X4MGDBAnaSDgoIMpudl1EEFXSVdXuVbe1hYmEXvJydoyXuQ3BIhIxhyApepHvkiK8GDfMOXoEjngw8+UIHHK6+8Unrf559/rs45f//9txqtEdJA6/XXXy/3njI99MADD6ifX3rpJXUufP/99/HRRx9h3rx5quDiyy+/LP1d5P2GDRuG1157TX0JL2v48OEGt2VfpI/G/v370bp1a/WzkFER/d+jbAAjIzJyLGRURkhKhOybpEHISJSOHJtrr71W/fzUU0+pGQzZZ1udz+028iHTKhKpXn311SpqkotEmzNnzlQ/y8GV+TGJLvVJ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iIjIc9l8Vduq0nV7l05pRERE5B50521zVm1xueAjOztbXSckJDh7V4iIiMiK87i0WXfKwnLWKi4uxunTpxEREQEfn7LLi1c9KpOg5sSJE1y0zo54nB2Dx5nH2ZPw8+z+x1nCCQk84uPj4evr614jH7LDdevWtet7yAHnirn2x+PsGDzOPM6ehJ9n9z7OlY146LDahYiIiByKwQcRERE5lFcFH0FBQXj++efVNfE4uzt+nnmcPQk/z951nF0u4ZSIiIg8m1eNfBAREZHzMfggIiIih2LwQURERA7F4IOIiIgcymuCjw8//BD169dHcHAwOnfujG3btjl7lzzOCy+8oLrS6l+aN2/u7N1ye+vWrcOwYcNU10A5posWLTJ4XHLGn3vuOdSuXRshISHo168fDh8+7LT99dTjPHr06HKf70GDBjltf93VjBkz0LFjR9XFulatWrjppptw6NAhg23y8vIwfvx41KhRA+Hh4Rg+fDjS0tKcts+eepx79+5d7jP90EMPOWT/vCL4+P777zFp0iRVXrRz5060a9cOAwcOxJkzZ5y9ax6nVatWSElJKb1s2LDB2bvk9nJyctRnVgJoY15//XXMnDkTH3/8MbZu3YqwsDD1+Zb/wMl2x1lIsKH/+f722295iC20du1aFVhs2bIFv//+OwoLCzFgwAB1/HUef/xxLFmyBPPnz1fby5Ibt9xyC4+1jY+zGDt2rMFnWv4/cQiNF+jUqZNm/PjxpbeLioo08fHxmhkzZjh1vzzN888/r2nXrp2zd8OjyT/ZhQsXlt4uLi7WxMXFad54443S+zIyMjRBQUGab7/91kl76XnHWYwaNUpz4403Om2fPNWZM2fU8V67dm3p5zcgIEAzf/780m0OHDigttm8ebMT99SzjrO49tprNY899pjGGTx+5KOgoAA7duxQQ9H668fI7c2bNzt13zyRDPfLsHXDhg1x99134/jx487eJY929OhRpKamGny+ZW0FmVrk59v2/vjjDzWE3axZM4wbNw7nzp2zw7t4l8zMTHUdHR2truX/a/mWrv+ZlunbevXq8TNtw+Os88033yAmJgatW7fGtGnTkJubC0dwuYXlbC09PR1FRUWIjY01uF9uHzx40Gn75YnkhDdnzhz1H7MM302fPh09e/bEvn371Lwj2Z4EHsLY51v3GNmGTLnI0H+DBg1w5MgR/Oc//8H111+vToh+fn48zFauYj5x4kR0795dnfyEfG4DAwNRrVo1g235mbbtcRZ33XUXEhMT1RfGPXv24Mknn1R5IT/99BPszeODD3Ic+Y9Yp23btioYkQ/2Dz/8gDFjxvBPQW7tzjvvLP25TZs26jPeqFEjNRrSt29fp+6bu5KcBPlywtww5xznBx980OAzLUnr8lmW4Fo+2/bk8dMuMpwk30rKZkrL7bi4OKftlzeQby5NmzZFcnKys3fFY+k+w/x8O55MLcr/L/x8W+eRRx7B0qVLsWbNGtStW9fgMy3T5RkZGQbb8/9s2x5nY+QLo3DEZ9rjgw8ZvuvQoQNWrVplMAQlt7t27erUffN0Fy9eVBG0RNNkHzIFIP9Z63++s7KyVNULP9/2dfLkSZXzwc+3ZSSfV06ICxcuxOrVq9VnWJ/8fx0QEGDwmZapAMkf42fadsfZmKSkJHXtiM+0V0y7SJntqFGjcM0116BTp0549913VbnRfffd5+xd8yhTpkxRfRJkqkVK46S0WUadRowY4exdc/sgTv+biCSZyn8SkjgmSXgyl/vf//4XTZo0Uf/BPPvss2oOV+r6yTbHWS6SwyT9JiTYk6B66tSpaNy4sSprJsumAObNm4eff/5Z5YLpcpMkUVr61Mi1TNPK/9ty3CMjIzFhwgQVeHTp0oWH2kbHWT7D8vjgwYNVPxXJ+ZAS5169eqkpRbvTeIn3339fU69ePU1gYKAqvd2yZYuzd8nj3HHHHZratWurY1ynTh11Ozk52dm75fbWrFmjSuTKXqT0U1du++yzz2piY2NViW3fvn01hw4dcvZue9Rxzs3N1QwYMEBTs2ZNVQaamJioGTt2rCY1NdXZu+12jB1juXzxxRel21y6dEnz8MMPa6pXr64JDQ3V3HzzzZqUlBSn7renHefjx49revXqpYmOjlb/bzRu3FjzxBNPaDIzMx2yfz4lO0lERETkEB6f80FERESuhcEHERERORSDDyIiInIoBh9ERETkUAw+iIiIyKEYfBAREZFDMfggIiIih2LwQURERA7F4IOIiIgcisEHERERORSDDyIiInIoBh9EREQER/p/suaYral7JoEAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tsr_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/tsr_15mw.csv\"\n", + "pitch_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/pitch_15mw.csv\"\n", + "check_interp(tsr_15mw_csv, pitch_15mw_csv)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "51835dd1", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tsr_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/tsr_5mw.csv\"\n", + "pitch_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/pitch_5mw.csv\"\n", + "check_interp(tsr_15mw_csv, pitch_15mw_csv)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2cdf23d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mitrotor-l4Gn_-ln-py3.12", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From ad926ef68eb9fa7cb3847c7ba86ed60bbcae2cb7 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Mon, 5 Jan 2026 15:31:37 -0500 Subject: [PATCH 03/50] Working attempt, but power values uncertian --- MITRotor/FlorisInterface/FlorisInterface.py | 140 +- MITRotor/Geometry.py | 4 +- examples/example_05_floris_integration.ipynb | 145 +- examples/example_05_floris_integration.py | 35 + poetry.lock | 2015 ++++++++++-------- pyproject.toml | 2 +- 6 files changed, 1394 insertions(+), 947 deletions(-) create mode 100644 examples/example_05_floris_integration.py diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index b04e131..d4285fa 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -1,16 +1,25 @@ import numpy as np +import os from attrs import define, field from typing import Literal, Optional from scipy.interpolate import interp1d # FLORIS Imports from floris.type_dec import floris_float_type, NDArrayFloat from floris.core.turbine.operation_models import BaseOperationModel -from floris.core.rotor_velocity import average_velocity -# MITRotor Imports +from floris.core.rotor_velocity import average_velocity, rotor_velocity_air_density_correction +# MITRotor / UMM Imports from MITRotor.ReferenceTurbines import IEA15MW from MITRotor.Momentum import UnifiedMomentum from MITRotor.Geometry import BEMGeometry -from MITRotor.BEMSolver import BEM, BEMSolution +from MITRotor.BEMSolver import BEM +from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw + +def default_bem_factory(): + return BEM( + rotor=IEA15MW(), + momentum_model=UnifiedMomentum(averaging="rotor"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + ) def csv_to_interp(csv_file): # read in csv @@ -23,7 +32,7 @@ def csv_to_interp(csv_file): x = x[idx] y = y[idx] # return interpolator for y - return interp1d(x, y, kind="linear", bounds_error=False, fill_value="extrapolate") + return interp1d(x, y, kind="linear", fill_value=0.0001, bounds_error=False) @define class MITRotorTurbine(BaseOperationModel): @@ -31,71 +40,100 @@ class MITRotorTurbine(BaseOperationModel): A turbine operation model that calls MITRotor. """ # user can define a BEM model if they want a different rotor, momentum model, or geometry - default_bem = BEM( - rotor=IEA15MW(), - momentum_model = UnifiedMomentum(averaging = "rotor"), - geometry = BEMGeometry(Nr = 10, Ntheta = 20), - ) - bem_model = field(init = False, default = default_bem, type = BEM) + bem_model = field(init = True, factory = default_bem_factory, type = BEM) # save most recent solution by unique floris arguments - _bem_sol = field(init=False, default=None, type = Optional[list[BEMSolution]]) - _avg_vels = field(init=False, default=None, type = Optional[NDArrayFloat]) _last_key = field(init=False, default=None, type = bytes) - # save blade pitch and tsr interpolation objects - # TODO -> figure out how to make csv change with rotor type - _pitch_interp = field(init = False, default = csv_to_interp("pitch_15mw.csv")) - _tsr_interp = field(init = False, default= csv_to_interp("tsr_15mw.csv")) + _a = field(init=False, default=None, type = NDArrayFloat) + _Ct = field(init=False, default=None, type = NDArrayFloat) + _power = field(init=False, default=None, type = NDArrayFloat) + # user can define csv paths for pitch and tsr values + module_dir = os.path.dirname(__file__) + default_pitch_csv = os.path.join(module_dir, "pitch_15mw.csv") + default_tsr_csv = os.path.join(module_dir, "tsr_15mw.csv") + pitch_csv = field(init = True, default = default_pitch_csv, type = str) + tsr_csv = field(init = True, default= default_tsr_csv, type = str) + # create interp objects based on pitch and tsr csvs + _pitch_interp = field(init=False, default=None, type = interp1d, repr = False) + _tsr_interp = field(init=False, default=None, type = interp1d, repr = False) - def _get_solution_key(self, velocities: np.ndarray) -> bytes: # TODO: add more inputs + def __attrs_post_init__(self): + self._pitch_interp = csv_to_interp(self.pitch_csv) + self._tsr_interp = csv_to_interp(self.tsr_csv) + + def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_angles: np.ndarray) -> tuple: # Fast, deterministic, and explicit - return velocities.tobytes() + return velocities.tobytes(), yaw_angles.tobytes(), tilt_angles.tobytes() - def _get_solutions(self, + def _update_solution(self, + power_thrust_table: dict, velocities: NDArrayFloat, + air_density: float, yaw_angles: NDArrayFloat, tilt_angles: NDArrayFloat, + average_method: str = "cubic-mean", + cubature_weights: NDArrayFloat | None = None, + **kwargs, ): n_findex, n_turbines = yaw_angles.shape # create cache key for current inputs - key = self._get_solution_key(velocities) # TODO: add more inputs + key = self._get_state_key(velocities, yaw_angles, tilt_angles) # TODO: add more inputs # update solution if conditions are different if key != self._last_key: - self._bem_sol = [None] * n_findex - self._avg_vels = np.empty((n_findex, n_turbines), dtype=velocities.dtype) + # save new key and clear fields self._last_key = key + self._a = np.empty((n_findex, n_turbines), dtype=floris_float_type) + self._Ct = np.empty((n_findex, n_turbines), dtype=floris_float_type) + self._power = np.empty((n_findex, n_turbines), dtype=floris_float_type) + + # compute the power-effective wind speed across the rotor + rotor_average_velocities = average_velocity( + velocities=velocities, + method=average_method, + cubature_weights=cubature_weights, + ) + # update effective velocities for air density + rotor_effective_velocities = rotor_velocity_air_density_correction( + velocities=rotor_average_velocities, + air_density=air_density, + ref_air_density=power_thrust_table["ref_air_density"] + ) # loop over flow conditions for findex in range(n_findex): - cond_vels, cond_yaws, cond_tilts = velocities[findex], yaw_angles[findex], tilt_angles[findex] - rotor_avg_vels = average_velocity(cond_vels, method="cubic-mean") # TODO: does method need to be user input? - pitch_vals = self._pitch_interp(rotor_avg_vels) - tsr_vals = self._tsr_interp(rotor_avg_vels) - self._bem_sol[findex] = self.bem_model(pitch_vals, tsr_vals, yaw = cond_yaws, tilt = cond_tilts) - self._avg_vels[findex] = rotor_avg_vels + for tindex in range(n_turbines): + vel = rotor_effective_velocities[findex, tindex] + yaw, tilt = np.deg2rad(yaw_angles[findex, tindex]), np.deg2rad(tilt_angles[findex, tindex]) + pitch_val = np.deg2rad(self._pitch_interp(vel)) + tsr_val = self._tsr_interp(vel) + bem_sol = self.bem_model(pitch_val, tsr_val, yaw = yaw, tilt = tilt) + self._a[findex, tindex] = bem_sol.a() + self._Ct[findex, tindex] = bem_sol.Ct() + # calculate power + rotor_area = np.pi * self.bem_model.rotor.R**2 + rotor_uinfty = vel * np.cos(calc_eff_yaw(yaw, tilt)) - return self._bem_sol - - def power(self, - velocities: NDArrayFloat, - yaw_angles: NDArrayFloat, - tilt_angles: NDArrayFloat, - **_ - ) -> NDArrayFloat: - return self._get_solutions(velocities, yaw_angles, tilt_angles).Cp() # TODO: what type of averaging do we want? AND make into POWER + # Construct power interpolant + power_interpolator = interp1d( + power_thrust_table["wind_speed"], + power_thrust_table["power"], + fill_value=0.0, + bounds_error=False, + ) + # Compute power + power = power_interpolator(rotor_uinfty) * 1e3 # --> I am not sure the rotor_uinfty is the right value... + self._power[findex, tindex] = power # it seems like using Cp (below) should be correct... plot power interpolator... + # self._power[findex, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_uinfty)**3 - def thrust_coefficient(self, - velocities: NDArrayFloat, - yaw_angles: NDArrayFloat, - tilt_angles: NDArrayFloat, - **_ - ) -> NDArrayFloat: - return self._get_solutions(velocities, yaw_angles, tilt_angles).Ct() # TODO: what type of averaging do we want? + return + + def power(self, **kwargs) -> NDArrayFloat: + self._update_solution(**kwargs) + return self._power + def thrust_coefficient(self, **kwargs) -> NDArrayFloat: + self._update_solution(**kwargs) + return self._Ct - def axial_induction(self, - velocities: NDArrayFloat, - yaw_angles: NDArrayFloat, - tilt_angles: NDArrayFloat, - **_ - ) -> NDArrayFloat: - return self._get_solutions(velocities, yaw_angles, tilt_angles).a() # TODO: what type of averaging do we want? \ No newline at end of file + def axial_induction(self, **kwargs) -> NDArrayFloat: + self._update_solution(**kwargs) + return self._a \ No newline at end of file diff --git a/MITRotor/Geometry.py b/MITRotor/Geometry.py index 09cac9d..2e812ba 100644 --- a/MITRotor/Geometry.py +++ b/MITRotor/Geometry.py @@ -42,12 +42,12 @@ def cartesian(self, yaw: float, tilt: float) -> Tuple[ArrayLike, ...]: return X, Y, Z def annulus_average(self, X: ArrayLike): - X_azim = 1 / (2 * np.pi) * np.trapz(X, self.theta_mesh, axis=-1) + X_azim = 1 / (2 * np.pi) * np.trapezoid(X, self.theta_mesh, axis=-1) return X_azim def rotor_average(self, X: ArrayLike): # Takes annulus average quantities and performs rotor average - X_rotor = 2 * np.trapz(X * self.mu, self.mu) + X_rotor = 2 * np.trapezoid(X * self.mu, self.mu) return X_rotor diff --git a/examples/example_05_floris_integration.ipynb b/examples/example_05_floris_integration.ipynb index 5cafc1b..9552036 100644 --- a/examples/example_05_floris_integration.ipynb +++ b/examples/example_05_floris_integration.ipynb @@ -2,19 +2,20 @@ "cells": [ { "cell_type": "code", - "execution_count": 26, + "execution_count": 7, "id": "eb249327", "metadata": {}, "outputs": [], "source": [ - "from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp\n", + "from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, MITRotorTurbine\n", + "from floris import FlorisModel, TimeSeries\n", "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 8, "id": "9cc53ad8", "metadata": {}, "outputs": [], @@ -40,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 9, "id": "08c83a7f", "metadata": {}, "outputs": [ @@ -53,7 +54,7 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAAGdCAYAAACyzRGfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAXh5JREFUeJzt3Qd4k2XXB/B/926hFFoKpey9FNlDZMtw4UJFUMRPRBQBUV4n+irugQOVVwUHDlCQoaAM2UNGGTKkCLLaQoEOWjpo813nTlOSNmmTNDv/33XlSpM8SZ4+DTwn933OuX00Go0GRERERA7i66g3IiIiImLwQURERA7HkQ8iIiJyKAYfRERE5FAMPoiIiMihGHwQERGRQzH4ICIiIodi8EFEREQO5Q8XU1xcjNOnTyMiIgI+Pj7O3h0iIiIyg/Qszc7ORnx8PHx9fd0r+JDAIyEhwdm7QURERFY4ceIE6tat617Bh4x46HY+MjLS2btDREREZsjKylKDB7rzuFsFH7qpFgk8GHwQERG5F3NSJphwSkRERA7F4IOIiIgcisEHEREROZTL5XwQEXlDSeLly5dRVFTk7F0hskhAQAD8/PxQVQw+iIgcqKCgACkpKcjNzeVxJ7dMJpUy2vDw8Cq9DoMPIiIHNlE8evSo+uYojZgCAwPZTJHcasTu7NmzOHnyJJo0aVKlERAGH0REDhz1kABEeiGEhobyuJPbqVmzJo4dO4bCwsIqBR9MOCUicrDKWk8TuSpbLXvCfwFERETkUFUKPl599VUVBU2cOLH0vry8PIwfPx41atRQCSnDhw9HWlqaLfaViIjIbY0ePRo33XSTy7yOWwYff/75Jz755BO0bdvW4P7HH38cS5Yswfz587F27Vq1UNwtt9xii30lIiInkC+ZFV1eeOEFtd3ChQvRpUsXREVFqfU9WrVqZfDldM6cOaXPkamn2rVr44477sDx48crfH95XrVq1Sza5969exu8tzs6duyYOlZJSUkG97/33nvqmHhd8HHx4kXcfffdmD17NqpXr156f2ZmJj777DO8/fbb6NOnDzp06IAvvvgCmzZtwpYtW2y530RE5CBSGqy7vPvuu2rdLf37pkyZglWrVqlAQka7t23bhh07duDll19WiYn6dM89deoUfvzxRxw6dAi33XabSycJu5qoqCiLgzGPCD5kWmXIkCHo16+fwf3yYZMPmv79zZs3R7169bB582ajr5Wfn69WwtO/2ENqZh7eW3kYr/560C6vT0TkqeLi4kovcuKTb+P698kUu4x4d+/eHU888QSaNWuGpk2bqqmBDz/80OC1dM+VUY9u3bphzJgxKlix5P9+GWlp3749vvrqK9SvX1/t05133ons7OzSaQkZeZcRAt1Ii4wiiH379uH6669X+xwbG4uRI0ciPT3dYMTkkUceUaMmMTExGDhwYOl+z5o1Sz03JCQEDRs2xIIFCwz2a+/eveqLtzwuqQcPPvig+rJuyvLly9GjRw8VSMj2Q4cOxZEjR0ofb9Cggbq+6qqr1PvLvhmbdpHz6KOPPopatWohODhYvabMTuj88ccf6vkSIF5zzTWq0kqOvQR+bhN8fPfdd9i5cydmzJhR7rHU1FRVt142IpM/sDxmjLyOfHB0FylBs4ez2fl4Z+XfmLvpGHILLtvlPYiIrOmdIP8nOfoi72tLElD89ddf6uRurjNnzqipGinZtLRsU07SixYtwtKlS9VFgg3JQxQSdHTt2hVjx44tHZ2Rc0tGRoYKDuRkvn37dnXyl5zE22+/3eC1586dq85lGzduxMcff1x6/7PPPqtGdnbv3q1G/yXgOXDggHosJydHBSoyGyAnfkk9WLlypQpkTMnJycGkSZPUvkhgIFNRN998syrHFhKUCXkd+R1++ukno68zdepUNYok+y3n58aNG6t9OX/+vMF2Tz/9NN566y31fv7+/rj//vvhLBb1+Thx4gQee+wx/P777yq6soVp06apg68j0a89ApDWdSKREB2CE+cvYc3BsxjStrbN34OIyFKXCovQ8rkVDj9w+18ciNBA27V6mjBhAtavX482bdogMTFR5X4MGDBAnaSDgoIMpudl1EEFXSVdXuVbe1hYmEXvJydoyXuQ3BIhIxhyApepHvkiK8GDfMOXoEjngw8+UIHHK6+8Unrf559/rs45f//9txqtEdJA6/XXXy/3njI99MADD6ifX3rpJXUufP/99/HRRx9h3rx5quDiyy+/LP1d5P2GDRuG1157TX0JL2v48OEGt2VfpI/G/v370bp1a/WzkFER/d+jbAAjIzJyLGRURkhKhOybpEHISJSOHJtrr71W/fzUU0+pGQzZZ1udz+028iHTKhKpXn311SpqkotEmzNnzlQ/y8GV+TGJLvVJ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iIjIc9l8Vduq0nV7l05pRERE5B50521zVm1xueAjOztbXSckJDh7V4iIiMiK87i0WXfKwnLWKi4uxunTpxEREQEfn7LLi1c9KpOg5sSJE1y0zo54nB2Dx5nH2ZPw8+z+x1nCCQk84uPj4evr614jH7LDdevWtet7yAHnirn2x+PsGDzOPM6ehJ9n9z7OlY146LDahYiIiByKwQcRERE5lFcFH0FBQXj++efVNfE4uzt+nnmcPQk/z951nF0u4ZSIiIg8m1eNfBAREZHzMfggIiIih2LwQURERA7F4IOIiIgcymuCjw8//BD169dHcHAwOnfujG3btjl7lzzOCy+8oLrS6l+aN2/u7N1ye+vWrcOwYcNU10A5posWLTJ4XHLGn3vuOdSuXRshISHo168fDh8+7LT99dTjPHr06HKf70GDBjltf93VjBkz0LFjR9XFulatWrjppptw6NAhg23y8vIwfvx41KhRA+Hh4Rg+fDjS0tKcts+eepx79+5d7jP90EMPOWT/vCL4+P777zFp0iRVXrRz5060a9cOAwcOxJkzZ5y9ax6nVatWSElJKb1s2LDB2bvk9nJyctRnVgJoY15//XXMnDkTH3/8MbZu3YqwsDD1+Zb/wMl2x1lIsKH/+f722295iC20du1aFVhs2bIFv//+OwoLCzFgwAB1/HUef/xxLFmyBPPnz1fby5Ibt9xyC4+1jY+zGDt2rMFnWv4/cQiNF+jUqZNm/PjxpbeLioo08fHxmhkzZjh1vzzN888/r2nXrp2zd8OjyT/ZhQsXlt4uLi7WxMXFad54443S+zIyMjRBQUGab7/91kl76XnHWYwaNUpz4403Om2fPNWZM2fU8V67dm3p5zcgIEAzf/780m0OHDigttm8ebMT99SzjrO49tprNY899pjGGTx+5KOgoAA7duxQQ9H668fI7c2bNzt13zyRDPfLsHXDhg1x99134/jx487eJY929OhRpKamGny+ZW0FmVrk59v2/vjjDzWE3axZM4wbNw7nzp2zw7t4l8zMTHUdHR2truX/a/mWrv+ZlunbevXq8TNtw+Os88033yAmJgatW7fGtGnTkJubC0dwuYXlbC09PR1FRUWIjY01uF9uHzx40Gn75YnkhDdnzhz1H7MM302fPh09e/bEvn371Lwj2Z4EHsLY51v3GNmGTLnI0H+DBg1w5MgR/Oc//8H111+vToh+fn48zFauYj5x4kR0795dnfyEfG4DAwNRrVo1g235mbbtcRZ33XUXEhMT1RfGPXv24Mknn1R5IT/99BPszeODD3Ic+Y9Yp23btioYkQ/2Dz/8gDFjxvBPQW7tzjvvLP25TZs26jPeqFEjNRrSt29fp+6bu5KcBPlywtww5xznBx980OAzLUnr8lmW4Fo+2/bk8dMuMpwk30rKZkrL7bi4OKftlzeQby5NmzZFcnKys3fFY+k+w/x8O55MLcr/L/x8W+eRRx7B0qVLsWbNGtStW9fgMy3T5RkZGQbb8/9s2x5nY+QLo3DEZ9rjgw8ZvuvQoQNWrVplMAQlt7t27erUffN0Fy9eVBG0RNNkHzIFIP9Z63++s7KyVNULP9/2dfLkSZXzwc+3ZSSfV06ICxcuxOrVq9VnWJ/8fx0QEGDwmZapAMkf42fadsfZmKSkJHXtiM+0V0y7SJntqFGjcM0116BTp0549913VbnRfffd5+xd8yhTpkxRfRJkqkVK46S0WUadRowY4exdc/sgTv+biCSZyn8SkjgmSXgyl/vf//4XTZo0Uf/BPPvss2oOV+r6yTbHWS6SwyT9JiTYk6B66tSpaNy4sSprJsumAObNm4eff/5Z5YLpcpMkUVr61Mi1TNPK/9ty3CMjIzFhwgQVeHTp0oWH2kbHWT7D8vjgwYNVPxXJ+ZAS5169eqkpRbvTeIn3339fU69ePU1gYKAqvd2yZYuzd8nj3HHHHZratWurY1ynTh11Ozk52dm75fbWrFmjSuTKXqT0U1du++yzz2piY2NViW3fvn01hw4dcvZue9Rxzs3N1QwYMEBTs2ZNVQaamJioGTt2rCY1NdXZu+12jB1juXzxxRel21y6dEnz8MMPa6pXr64JDQ3V3HzzzZqUlBSn7renHefjx49revXqpYmOjlb/bzRu3FjzxBNPaDIzMx2yfz4lO0lERETkEB6f80FERESuhcEHERERORSDDyIiInIoBh9ERETkUAw+iIiIyKEYfBAREZFDMfggIiIih2LwQURERA7F4IOIiIgcisEHERERORSDDyIiInIoBh9EREQER/p/suaYral7JoEAAAAASUVORK5CYII=", + "image/png": "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", "text/plain": [ "
" ] @@ -70,13 +71,20 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 10, "id": "51835dd1", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -91,10 +99,131 @@ "check_interp(tsr_15mw_csv, pitch_15mw_csv)" ] }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2a93558a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Powers [W]:\n", + " [[1753954.45917917 354990.76412771]\n", + " [3417797.00509157 737171.66537995]\n", + " [5000000. 4927707.14320011]] \n", + "\n", + "Thrust coefficients [-]:\n", + " [[0.78715145 0.9353766 ]\n", + " [0.78387889 0.86092059]\n", + " [0.55092883 0.74517368]] \n", + "\n", + "Axial induction factors [-]:\n", + " [[0.26932244 0.37289433]\n", + " [0.26755586 0.31353324]\n", + " [0.16493614 0.24759837]] \n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/sky/Library/Caches/pypoetry/virtualenvs/mitrotor-l4Gn_-ln-py3.12/lib/python3.12/site-packages/floris/core/flow_field.py:172: UserWarning: 'where' used without 'out', expect unitialized memory in output. If this is intentional, use out=None.\n", + " * np.power(\n" + ] + } + ], + "source": [ + "from floris.core.turbine.unified_momentum_model import UnifiedMomentumModelTurbine\n", + "from floris import FlorisModel\n", + "\n", + "fmodel = FlorisModel(\"defaults\")\n", + "\n", + "time_series = TimeSeries(\n", + " wind_directions=np.array([270.0, 270.0, 280.0]),\n", + " wind_speeds=np.array([8.0, 10.0, 12.0]),\n", + " turbulence_intensities=np.array([0.06, 0.06, 0.06]),\n", + ")\n", + "\n", + "fmodel.set(\n", + " layout_x = [0.0, 500.0],\n", + " layout_y = [0.0, 0.0],\n", + " wind_data=time_series,\n", + ")\n", + "\n", + "fmodel.run()\n", + "\n", + "print(\"Powers [W]:\\n\", fmodel.get_turbine_powers(), \"\\n\")\n", + "print(\"Thrust coefficients [-]:\\n\", fmodel.get_turbine_thrust_coefficients(), \"\\n\")\n", + "print(\"Axial induction factors [-]:\\n\", fmodel.get_turbine_axial_induction_factors(), \"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c7d9b5ae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Powers [W]:\n", + " [[ -80385.81346439 35955.07110895]\n", + " [-151917.60066 85753.35035653]\n", + " [-190271.12187713 332785.69634393]] \n", + "\n", + "Thrust coefficients [-]:\n", + " [[0.73380279 0.74621482]\n", + " [0.66198028 0.74239241]\n", + " [0.41175519 0.5029464 ]] \n", + "\n", + "Axial induction factors [-]:\n", + " [[0.34782061 0.35018336]\n", + " [0.30308838 0.35179638]\n", + " [0.18725075 0.22345784]] \n", + "\n" + ] + } + ], + "source": [ + "from floris import FlorisModel, TimeSeries\n", + "\n", + "fmodel = FlorisModel(\"defaults\")\n", + "\n", + "time_series = TimeSeries(\n", + " wind_directions=np.array([270.0, 270.0, 280.0]),\n", + " wind_speeds=np.array([8.0, 10.0, 12.0]),\n", + " turbulence_intensities=np.array([0.06, 0.06, 0.06]),\n", + ")\n", + "\n", + "yaw_angles = np.array([\n", + " [10.0, 0.0], # condition 1\n", + " [10.0, 0.0], # condition 2\n", + " [10.0, 0.0], # condition 3\n", + "])\n", + "\n", + "fmodel.set(\n", + " layout_x = [0.0, 500.0],\n", + " layout_y = [0.0, 0.0],\n", + " wind_data = time_series,\n", + " yaw_angles = yaw_angles\n", + ")\n", + "\n", + "fmodel.set_operation_model(MITRotorTurbine())\n", + "fmodel.run()\n", + "\n", + "print(\"Powers [W]:\\n\", fmodel.get_turbine_powers(), \"\\n\")\n", + "print(\"Thrust coefficients [-]:\\n\", fmodel.get_turbine_thrust_coefficients(), \"\\n\")\n", + "print(\"Axial induction factors [-]:\\n\", fmodel.get_turbine_axial_induction_factors(), \"\\n\")" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "a2cdf23d", + "id": "de761cdd", "metadata": {}, "outputs": [], "source": [] diff --git a/examples/example_05_floris_integration.py b/examples/example_05_floris_integration.py new file mode 100644 index 0000000..093b0cb --- /dev/null +++ b/examples/example_05_floris_integration.py @@ -0,0 +1,35 @@ +from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, MITRotorTurbine +from floris import FlorisModel, TimeSeries +from floris.core.turbine.unified_momentum_model import UnifiedMomentumModelTurbine +import numpy as np +import matplotlib.pyplot as plt + +from floris import FlorisModel, TimeSeries + +fmodel = FlorisModel("defaults") +time_series = TimeSeries( + wind_directions=np.array([270.0, 270.0, 280.0]), + wind_speeds=np.array([8.0, 10.0, 12.0]), + turbulence_intensities=np.array([0.06, 0.06, 0.06]), +) +yaw_angles = np.array([ + [0.0, 0.0], # condition 1 + [0.0, 0.0], # condition 2 + [0.0, 0.0], # condition 3 +]) + +fmodel.set( + layout_x = [0.0, 500.0], + layout_y = [0.0, 0.0], + wind_data = time_series, + yaw_angles = yaw_angles +) +fmodel.set_operation_model(UnifiedMomentumModelTurbine) + +# fmodel.set_operation_model(MITRotorTurbine()) + +fmodel.run() + +print("Powers [W]:\n", fmodel.get_turbine_powers(), "\n") +print("Thrust coefficients [-]:\n", fmodel.get_turbine_thrust_coefficients(), "\n") +print("Axial induction factors [-]:\n", fmodel.get_turbine_axial_induction_factors(), "\n") \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index b1ad6e6..c90a865 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,24 +2,23 @@ [[package]] name = "anyio" -version = "4.11.0" +version = "4.12.0" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc"}, - {file = "anyio-4.11.0.tar.gz", hash = "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4"}, + {file = "anyio-4.12.0-py3-none-any.whl", hash = "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb"}, + {file = "anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0"}, ] [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" -sniffio = ">=1.1" typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] -trio = ["trio (>=0.31.0)"] +trio = ["trio (>=0.31.0) ; python_version < \"3.10\"", "trio (>=0.32.0) ; python_version >= \"3.10\""] [[package]] name = "appnope" @@ -28,7 +27,7 @@ description = "Disable App Nap on macOS >= 10.9" optional = false python-versions = ">=3.6" groups = ["dev"] -markers = "platform_system == \"Darwin\" or sys_platform == \"darwin\" and python_version < \"3.11\"" +markers = "platform_system == \"Darwin\"" files = [ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, @@ -113,19 +112,19 @@ test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock [[package]] name = "asttokens" -version = "3.0.0" +version = "3.0.1" description = "Annotate AST trees with source code positions" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, - {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, + {file = "asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a"}, + {file = "asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7"}, ] [package.extras] -astroid = ["astroid (>=2,<4)"] -test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] +astroid = ["astroid (>=2,<5)"] +test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"] [[package]] name = "async-lru" @@ -169,33 +168,20 @@ files = [ [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] -[[package]] -name = "backcall" -version = "0.2.0" -description = "Specifications for callback functions passed in to an API" -optional = false -python-versions = "*" -groups = ["dev"] -markers = "python_version < \"3.11\"" -files = [ - {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, - {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, -] - [[package]] name = "beautifulsoup4" -version = "4.14.2" +version = "4.14.3" description = "Screen-scraping library" optional = false python-versions = ">=3.7.0" groups = ["dev"] files = [ - {file = "beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515"}, - {file = "beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e"}, + {file = "beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb"}, + {file = "beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86"}, ] [package.dependencies] -soupsieve = ">1.2" +soupsieve = ">=1.6.1" typing-extensions = ">=4.0.0" [package.extras] @@ -256,24 +242,23 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bleach" -version = "6.1.0" +version = "6.2.0" description = "An easy safelist-based HTML-sanitizing tool." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] markers = "python_version < \"3.11\"" files = [ - {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, - {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, + {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"}, + {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"}, ] [package.dependencies] -six = ">=1.9.0" -tinycss2 = {version = ">=1.1.0,<1.3", optional = true, markers = "extra == \"css\""} +tinycss2 = {version = ">=1.1.0,<1.5", optional = true, markers = "extra == \"css\""} webencodings = "*" [package.extras] -css = ["tinycss2 (>=1.1.0,<1.3)"] +css = ["tinycss2 (>=1.1.0,<1.5)"] [[package]] name = "bleach" @@ -297,14 +282,14 @@ css = ["tinycss2 (>=1.1.0,<1.5)"] [[package]] name = "certifi" -version = "2025.10.5" +version = "2026.1.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de"}, - {file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"}, + {file = "certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c"}, + {file = "certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120"}, ] [[package]] @@ -545,15 +530,15 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "click" -version = "8.3.0" +version = "8.3.1" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" groups = ["dev"] markers = "python_version >= \"3.11\"" files = [ - {file = "click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc"}, - {file = "click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"}, + {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, + {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, ] [package.dependencies] @@ -802,42 +787,42 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "debugpy" -version = "1.8.17" +version = "1.8.19" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "debugpy-1.8.17-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:c41d2ce8bbaddcc0009cc73f65318eedfa3dbc88a8298081deb05389f1ab5542"}, - {file = "debugpy-1.8.17-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:1440fd514e1b815edd5861ca394786f90eb24960eb26d6f7200994333b1d79e3"}, - {file = "debugpy-1.8.17-cp310-cp310-win32.whl", hash = "sha256:3a32c0af575749083d7492dc79f6ab69f21b2d2ad4cd977a958a07d5865316e4"}, - {file = "debugpy-1.8.17-cp310-cp310-win_amd64.whl", hash = "sha256:a3aad0537cf4d9c1996434be68c6c9a6d233ac6f76c2a482c7803295b4e4f99a"}, - {file = "debugpy-1.8.17-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:d3fce3f0e3de262a3b67e69916d001f3e767661c6e1ee42553009d445d1cd840"}, - {file = "debugpy-1.8.17-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:c6bdf134457ae0cac6fb68205776be635d31174eeac9541e1d0c062165c6461f"}, - {file = "debugpy-1.8.17-cp311-cp311-win32.whl", hash = "sha256:e79a195f9e059edfe5d8bf6f3749b2599452d3e9380484cd261f6b7cd2c7c4da"}, - {file = "debugpy-1.8.17-cp311-cp311-win_amd64.whl", hash = "sha256:b532282ad4eca958b1b2d7dbcb2b7218e02cb934165859b918e3b6ba7772d3f4"}, - {file = "debugpy-1.8.17-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:f14467edef672195c6f6b8e27ce5005313cb5d03c9239059bc7182b60c176e2d"}, - {file = "debugpy-1.8.17-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:24693179ef9dfa20dca8605905a42b392be56d410c333af82f1c5dff807a64cc"}, - {file = "debugpy-1.8.17-cp312-cp312-win32.whl", hash = "sha256:6a4e9dacf2cbb60d2514ff7b04b4534b0139facbf2abdffe0639ddb6088e59cf"}, - {file = "debugpy-1.8.17-cp312-cp312-win_amd64.whl", hash = "sha256:e8f8f61c518952fb15f74a302e068b48d9c4691768ade433e4adeea961993464"}, - {file = "debugpy-1.8.17-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:857c1dd5d70042502aef1c6d1c2801211f3ea7e56f75e9c335f434afb403e464"}, - {file = "debugpy-1.8.17-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:3bea3b0b12f3946e098cce9b43c3c46e317b567f79570c3f43f0b96d00788088"}, - {file = "debugpy-1.8.17-cp313-cp313-win32.whl", hash = "sha256:e34ee844c2f17b18556b5bbe59e1e2ff4e86a00282d2a46edab73fd7f18f4a83"}, - {file = "debugpy-1.8.17-cp313-cp313-win_amd64.whl", hash = "sha256:6c5cd6f009ad4fca8e33e5238210dc1e5f42db07d4b6ab21ac7ffa904a196420"}, - {file = "debugpy-1.8.17-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:045290c010bcd2d82bc97aa2daf6837443cd52f6328592698809b4549babcee1"}, - {file = "debugpy-1.8.17-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:b69b6bd9dba6a03632534cdf67c760625760a215ae289f7489a452af1031fe1f"}, - {file = "debugpy-1.8.17-cp314-cp314-win32.whl", hash = "sha256:5c59b74aa5630f3a5194467100c3b3d1c77898f9ab27e3f7dc5d40fc2f122670"}, - {file = "debugpy-1.8.17-cp314-cp314-win_amd64.whl", hash = "sha256:893cba7bb0f55161de4365584b025f7064e1f88913551bcd23be3260b231429c"}, - {file = "debugpy-1.8.17-cp38-cp38-macosx_15_0_x86_64.whl", hash = "sha256:8deb4e31cd575c9f9370042876e078ca118117c1b5e1f22c32befcfbb6955f0c"}, - {file = "debugpy-1.8.17-cp38-cp38-manylinux_2_34_x86_64.whl", hash = "sha256:b75868b675949a96ab51abc114c7163f40ff0d8f7d6d5fd63f8932fd38e9c6d7"}, - {file = "debugpy-1.8.17-cp38-cp38-win32.whl", hash = "sha256:17e456da14848d618662354e1dccfd5e5fb75deec3d1d48dc0aa0baacda55860"}, - {file = "debugpy-1.8.17-cp38-cp38-win_amd64.whl", hash = "sha256:e851beb536a427b5df8aa7d0c7835b29a13812f41e46292ff80b2ef77327355a"}, - {file = "debugpy-1.8.17-cp39-cp39-macosx_15_0_x86_64.whl", hash = "sha256:f2ac8055a0c4a09b30b931100996ba49ef334c6947e7ae365cdd870416d7513e"}, - {file = "debugpy-1.8.17-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:eaa85bce251feca8e4c87ce3b954aba84b8c645b90f0e6a515c00394a9f5c0e7"}, - {file = "debugpy-1.8.17-cp39-cp39-win32.whl", hash = "sha256:b13eea5587e44f27f6c48588b5ad56dcb74a4f3a5f89250443c94587f3eb2ea1"}, - {file = "debugpy-1.8.17-cp39-cp39-win_amd64.whl", hash = "sha256:bb1bbf92317e1f35afcf3ef0450219efb3afe00be79d8664b250ac0933b9015f"}, - {file = "debugpy-1.8.17-py2.py3-none-any.whl", hash = "sha256:60c7dca6571efe660ccb7a9508d73ca14b8796c4ed484c2002abba714226cfef"}, - {file = "debugpy-1.8.17.tar.gz", hash = "sha256:fd723b47a8c08892b1a16b2c6239a8b96637c62a59b94bb5dab4bac592a58a8e"}, + {file = "debugpy-1.8.19-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:fce6da15d73be5935b4438435c53adb512326a3e11e4f90793ea87cd9f018254"}, + {file = "debugpy-1.8.19-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:e24b1652a1df1ab04d81e7ead446a91c226de704ff5dde6bd0a0dbaab07aa3f2"}, + {file = "debugpy-1.8.19-cp310-cp310-win32.whl", hash = "sha256:327cb28c3ad9e17bc925efc7f7018195fd4787c2fe4b7af1eec11f1d19bdec62"}, + {file = "debugpy-1.8.19-cp310-cp310-win_amd64.whl", hash = "sha256:b7dd275cf2c99e53adb9654f5ae015f70415bbe2bacbe24cfee30d54b6aa03c5"}, + {file = "debugpy-1.8.19-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:c5dcfa21de1f735a4f7ced4556339a109aa0f618d366ede9da0a3600f2516d8b"}, + {file = "debugpy-1.8.19-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:806d6800246244004625d5222d7765874ab2d22f3ba5f615416cf1342d61c488"}, + {file = "debugpy-1.8.19-cp311-cp311-win32.whl", hash = "sha256:783a519e6dfb1f3cd773a9bda592f4887a65040cb0c7bd38dde410f4e53c40d4"}, + {file = "debugpy-1.8.19-cp311-cp311-win_amd64.whl", hash = "sha256:14035cbdbb1fe4b642babcdcb5935c2da3b1067ac211c5c5a8fdc0bb31adbcaa"}, + {file = "debugpy-1.8.19-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:bccb1540a49cde77edc7ce7d9d075c1dbeb2414751bc0048c7a11e1b597a4c2e"}, + {file = "debugpy-1.8.19-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:e9c68d9a382ec754dc05ed1d1b4ed5bd824b9f7c1a8cd1083adb84b3c93501de"}, + {file = "debugpy-1.8.19-cp312-cp312-win32.whl", hash = "sha256:6599cab8a783d1496ae9984c52cb13b7c4a3bd06a8e6c33446832a5d97ce0bee"}, + {file = "debugpy-1.8.19-cp312-cp312-win_amd64.whl", hash = "sha256:66e3d2fd8f2035a8f111eb127fa508469dfa40928a89b460b41fd988684dc83d"}, + {file = "debugpy-1.8.19-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:91e35db2672a0abaf325f4868fcac9c1674a0d9ad9bb8a8c849c03a5ebba3e6d"}, + {file = "debugpy-1.8.19-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:85016a73ab84dea1c1f1dcd88ec692993bcbe4532d1b49ecb5f3c688ae50c606"}, + {file = "debugpy-1.8.19-cp313-cp313-win32.whl", hash = "sha256:b605f17e89ba0ecee994391194285fada89cee111cfcd29d6f2ee11cbdc40976"}, + {file = "debugpy-1.8.19-cp313-cp313-win_amd64.whl", hash = "sha256:c30639998a9f9cd9699b4b621942c0179a6527f083c72351f95c6ab1728d5b73"}, + {file = "debugpy-1.8.19-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:1e8c4d1bd230067bf1bbcdbd6032e5a57068638eb28b9153d008ecde288152af"}, + {file = "debugpy-1.8.19-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d40c016c1f538dbf1762936e3aeb43a89b965069d9f60f9e39d35d9d25e6b809"}, + {file = "debugpy-1.8.19-cp314-cp314-win32.whl", hash = "sha256:0601708223fe1cd0e27c6cce67a899d92c7d68e73690211e6788a4b0e1903f5b"}, + {file = "debugpy-1.8.19-cp314-cp314-win_amd64.whl", hash = "sha256:8e19a725f5d486f20e53a1dde2ab8bb2c9607c40c00a42ab646def962b41125f"}, + {file = "debugpy-1.8.19-cp38-cp38-macosx_15_0_x86_64.whl", hash = "sha256:d9b6f633fd2865af2afba2beb0c1819b6ecd4aed1c8f90f5d1bbca3272306b10"}, + {file = "debugpy-1.8.19-cp38-cp38-manylinux_2_34_x86_64.whl", hash = "sha256:a21bfdea088f713df05fa246ba0520f6ba44dd7eaec224742f51987a6979a648"}, + {file = "debugpy-1.8.19-cp38-cp38-win32.whl", hash = "sha256:b1cb98e5325da3059ca24445fca48314bfddfdf65ce1b59ff07055e723f06bd2"}, + {file = "debugpy-1.8.19-cp38-cp38-win_amd64.whl", hash = "sha256:c9b9bf440141a36836bdbe4320a2b126bb38aafa85e1aed05d7bfbb0e2a278bf"}, + {file = "debugpy-1.8.19-cp39-cp39-macosx_15_0_x86_64.whl", hash = "sha256:c047177ab2d286451f242b855b650d313198c4a987140d4b35218b2855a64a4a"}, + {file = "debugpy-1.8.19-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:4468de0c30012d367944f0eab4ecb8371736e8ef9522a465f61214f344c11183"}, + {file = "debugpy-1.8.19-cp39-cp39-win32.whl", hash = "sha256:7b62c0f015120ede25e5124a5f9d8a424e1208e3d96a36c89958f046ee21fff6"}, + {file = "debugpy-1.8.19-cp39-cp39-win_amd64.whl", hash = "sha256:76f566baaf7f3e06adbe67ffedccd2ee911d1e486f55931939ce3f0fe1090774"}, + {file = "debugpy-1.8.19-py2.py3-none-any.whl", hash = "sha256:360ffd231a780abbc414ba0f005dad409e71c78637efe8f2bd75837132a41d38"}, + {file = "debugpy-1.8.19.tar.gz", hash = "sha256:eea7e5987445ab0b5ed258093722d5ecb8bb72217c5c9b1e21f64efe23ddebdb"}, ] [[package]] @@ -882,15 +867,15 @@ profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "exceptiongroup" -version = "1.3.0" +version = "1.3.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" groups = ["dev"] markers = "python_version < \"3.11\"" files = [ - {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, - {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, ] [package.dependencies] @@ -931,15 +916,13 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "floris" -version = "4.5.1" +version = "4.5" description = "A controls-oriented engineering wake model." optional = false python-versions = ">=3.9" groups = ["main"] -files = [ - {file = "floris-4.5.1-py3-none-any.whl", hash = "sha256:85dd2669319c3f4987a8231862eb2cb219c6738c9c042135f734d95b593d6961"}, - {file = "floris-4.5.1.tar.gz", hash = "sha256:7823f1a0d1d286fe2e6347972aaaef70d219b95e1c01e579e1bfadfd14a12504"}, -] +files = [] +develop = false [package.dependencies] attrs = "*" @@ -957,85 +940,166 @@ shapely = ">=2.0,<3.0" develop = ["isort (>=5.0,<6.0)", "pre-commit (>=4.0,<5.0)", "pytest (>=8.0,<9.0)", "pytest-benchmark (>=5.1,<6.0)", "ruff (>=0.9,<1.0)"] docs = ["bokeh (>=3.7,<4.0)", "jupyter-book (>=1.0,<2.0)", "sphinx-autodoc-typehints (>=2.0,<3.0)", "sphinx-book-theme (>=1.0,<2.0)", "sphinxcontrib-autoyaml (>=1.0,<2.0)", "sphinxcontrib.mermaid (>=1.0,<2.0)"] +[package.source] +type = "git" +url = "https://github.com/misi9170/floris.git" +reference = "feature/user-def-op-mod" +resolved_reference = "9c8fca03f1520ea943c3080ac1e3ec8294f2663d" + [[package]] name = "fonttools" -version = "4.60.1" +version = "4.60.2" description = "Tools to manipulate font files" optional = false python-versions = ">=3.9" groups = ["main", "examples"] +markers = "python_version < \"3.11\"" +files = [ + {file = "fonttools-4.60.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4e36fadcf7e8ca6e34d490eef86ed638d6fd9c55d2f514b05687622cfc4a7050"}, + {file = "fonttools-4.60.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e500fc9c04bee749ceabfc20cb4903f6981c2139050d85720ea7ada61b75d5c"}, + {file = "fonttools-4.60.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22efea5e784e1d1cd8d7b856c198e360a979383ebc6dea4604743b56da1cbc34"}, + {file = "fonttools-4.60.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:677aa92d84d335e4d301d8ba04afca6f575316bc647b6782cb0921943fcb6343"}, + {file = "fonttools-4.60.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:edd49d3defbf35476e78b61ff737ff5efea811acff68d44233a95a5a48252334"}, + {file = "fonttools-4.60.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:126839492b69cecc5baf2bddcde60caab2ffafd867bbae2a88463fce6078ca3a"}, + {file = "fonttools-4.60.2-cp310-cp310-win32.whl", hash = "sha256:ffcab6f5537136046ca902ed2491ab081ba271b07591b916289b7c27ff845f96"}, + {file = "fonttools-4.60.2-cp310-cp310-win_amd64.whl", hash = "sha256:9c68b287c7ffcd29dd83b5f961004b2a54a862a88825d52ea219c6220309ba45"}, + {file = "fonttools-4.60.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a2aed0a7931401b3875265717a24c726f87ecfedbb7b3426c2ca4d2812e281ae"}, + {file = "fonttools-4.60.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dea6868e9d2b816c9076cfea77754686f3c19149873bdbc5acde437631c15df1"}, + {file = "fonttools-4.60.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fa27f34950aa1fe0f0b1abe25eed04770a3b3b34ad94e5ace82cc341589678a"}, + {file = "fonttools-4.60.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:13a53d479d187b09bfaa4a35ffcbc334fc494ff355f0a587386099cb66674f1e"}, + {file = "fonttools-4.60.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fac5e921d3bd0ca3bb8517dced2784f0742bc8ca28579a68b139f04ea323a779"}, + {file = "fonttools-4.60.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:648f4f9186fd7f1f3cd57dbf00d67a583720d5011feca67a5e88b3a491952cfb"}, + {file = "fonttools-4.60.2-cp311-cp311-win32.whl", hash = "sha256:3274e15fad871bead5453d5ce02658f6d0c7bc7e7021e2a5b8b04e2f9e40da1a"}, + {file = "fonttools-4.60.2-cp311-cp311-win_amd64.whl", hash = "sha256:91d058d5a483a1525b367803abb69de0923fbd45e1f82ebd000f5c8aa65bc78e"}, + {file = "fonttools-4.60.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e0164b7609d2b5c5dd4e044b8085b7bd7ca7363ef8c269a4ab5b5d4885a426b2"}, + {file = "fonttools-4.60.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1dd3d9574fc595c1e97faccae0f264dc88784ddf7fbf54c939528378bacc0033"}, + {file = "fonttools-4.60.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:98d0719f1b11c2817307d2da2e94296a3b2a3503f8d6252a101dca3ee663b917"}, + {file = "fonttools-4.60.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9d3ea26957dd07209f207b4fff64c702efe5496de153a54d3b91007ec28904dd"}, + {file = "fonttools-4.60.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ee301273b0850f3a515299f212898f37421f42ff9adfc341702582ca5073c13"}, + {file = "fonttools-4.60.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c6eb4694cc3b9c03b7c01d65a9cf35b577f21aa6abdbeeb08d3114b842a58153"}, + {file = "fonttools-4.60.2-cp312-cp312-win32.whl", hash = "sha256:57f07b616c69c244cc1a5a51072eeef07dddda5ebef9ca5c6e9cf6d59ae65b70"}, + {file = "fonttools-4.60.2-cp312-cp312-win_amd64.whl", hash = "sha256:310035802392f1fe5a7cf43d76f6ff4a24c919e4c72c0352e7b8176e2584b8a0"}, + {file = "fonttools-4.60.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2bb5fd231e56ccd7403212636dcccffc96c5ae0d6f9e4721fa0a32cb2e3ca432"}, + {file = "fonttools-4.60.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:536b5fab7b6fec78ccf59b5c59489189d9d0a8b0d3a77ed1858be59afb096696"}, + {file = "fonttools-4.60.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b9288fc38252ac86a9570f19313ecbc9ff678982e0f27c757a85f1f284d3400"}, + {file = "fonttools-4.60.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93fcb420791d839ef592eada2b69997c445d0ce9c969b5190f2e16828ec10607"}, + {file = "fonttools-4.60.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7916a381b094db4052ac284255186aebf74c5440248b78860cb41e300036f598"}, + {file = "fonttools-4.60.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58c8c393d5e16b15662cfc2d988491940458aa87894c662154f50c7b49440bef"}, + {file = "fonttools-4.60.2-cp313-cp313-win32.whl", hash = "sha256:19c6e0afd8b02008caa0aa08ab896dfce5d0bcb510c49b2c499541d5cb95a963"}, + {file = "fonttools-4.60.2-cp313-cp313-win_amd64.whl", hash = "sha256:6a500dc59e11b2338c2dba1f8cf11a4ae8be35ec24af8b2628b8759a61457b76"}, + {file = "fonttools-4.60.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:9387c532acbe323bbf2a920f132bce3c408a609d5f9dcfc6532fbc7e37f8ccbb"}, + {file = "fonttools-4.60.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6f1c824185b5b8fb681297f315f26ae55abb0d560c2579242feea8236b1cfef"}, + {file = "fonttools-4.60.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:55a3129d1e4030b1a30260f1b32fe76781b585fb2111d04a988e141c09eb6403"}, + {file = "fonttools-4.60.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b196e63753abc33b3b97a6fd6de4b7c4fef5552c0a5ba5e562be214d1e9668e0"}, + {file = "fonttools-4.60.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de76c8d740fb55745f3b154f0470c56db92ae3be27af8ad6c2e88f1458260c9a"}, + {file = "fonttools-4.60.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ba6303225c95998c9fda2d410aa792c3d2c1390a09df58d194b03e17583fa25"}, + {file = "fonttools-4.60.2-cp314-cp314-win32.whl", hash = "sha256:0a89728ce10d7c816fedaa5380c06d2793e7a8a634d7ce16810e536c22047384"}, + {file = "fonttools-4.60.2-cp314-cp314-win_amd64.whl", hash = "sha256:fa8446e6ab8bd778b82cb1077058a2addba86f30de27ab9cc18ed32b34bc8667"}, + {file = "fonttools-4.60.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4063bc81ac5a4137642865cb63dd270e37b3cd1f55a07c0d6e41d072699ccca2"}, + {file = "fonttools-4.60.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ebfdb66fa69732ed604ab8e2a0431e6deff35e933a11d73418cbc7823d03b8e1"}, + {file = "fonttools-4.60.2-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50b10b3b1a72d1d54c61b0e59239e1a94c0958f4a06a1febf97ce75388dd91a4"}, + {file = "fonttools-4.60.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:beae16891a13b4a2ddec9b39b4de76092a3025e4d1c82362e3042b62295d5e4d"}, + {file = "fonttools-4.60.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:522f017fdb3766fd5d2d321774ef351cc6ce88ad4e6ac9efe643e4a2b9d528db"}, + {file = "fonttools-4.60.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82cceceaf9c09a965a75b84a4b240dd3768e596ffb65ef53852681606fe7c9ba"}, + {file = "fonttools-4.60.2-cp314-cp314t-win32.whl", hash = "sha256:bbfbc918a75437fe7e6d64d1b1e1f713237df1cf00f3a36dedae910b2ba01cee"}, + {file = "fonttools-4.60.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0e5cd9b0830f6550d58c84f3ab151a9892b50c4f9d538c5603c0ce6fff2eb3f1"}, + {file = "fonttools-4.60.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a3c75b8b42f7f93906bdba9eb1197bb76aecbe9a0a7cf6feec75f7605b5e8008"}, + {file = "fonttools-4.60.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0f86c8c37bc0ec0b9c141d5e90c717ff614e93c187f06d80f18c7057097f71bc"}, + {file = "fonttools-4.60.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe905403fe59683b0e9a45f234af2866834376b8821f34633b1c76fb731b6311"}, + {file = "fonttools-4.60.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38ce703b60a906e421e12d9e3a7f064883f5e61bb23e8961f4be33cfe578500b"}, + {file = "fonttools-4.60.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9e810c06f3e79185cecf120e58b343ea5a89b54dd695fd644446bcf8c026da5e"}, + {file = "fonttools-4.60.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:38faec8cc1d12122599814d15a402183f5123fb7608dac956121e7c6742aebc5"}, + {file = "fonttools-4.60.2-cp39-cp39-win32.whl", hash = "sha256:80a45cf7bf659acb7b36578f300231873daba67bd3ca8cce181c73f861f14a37"}, + {file = "fonttools-4.60.2-cp39-cp39-win_amd64.whl", hash = "sha256:c355d5972071938e1b1e0f5a1df001f68ecf1a62f34a3407dc8e0beccf052501"}, + {file = "fonttools-4.60.2-py3-none-any.whl", hash = "sha256:73cf92eeda67cf6ff10c8af56fc8f4f07c1647d989a979be9e388a49be26552a"}, + {file = "fonttools-4.60.2.tar.gz", hash = "sha256:d29552e6b155ebfc685b0aecf8d429cb76c14ab734c22ef5d3dea6fdf800c92c"}, +] + +[package.extras] +all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.45.0)", "unicodedata2 (>=17.0.0) ; python_version <= \"3.14\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] +lxml = ["lxml (>=4.0)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.45.0)"] +symfont = ["sympy"] +type1 = ["xattr ; sys_platform == \"darwin\""] +unicode = ["unicodedata2 (>=17.0.0) ; python_version <= \"3.14\""] +woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] + +[[package]] +name = "fonttools" +version = "4.61.1" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.10" +groups = ["main", "examples"] +markers = "python_version >= \"3.11\"" files = [ - {file = "fonttools-4.60.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9a52f254ce051e196b8fe2af4634c2d2f02c981756c6464dc192f1b6050b4e28"}, - {file = "fonttools-4.60.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7420a2696a44650120cdd269a5d2e56a477e2bfa9d95e86229059beb1c19e15"}, - {file = "fonttools-4.60.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee0c0b3b35b34f782afc673d503167157094a16f442ace7c6c5e0ca80b08f50c"}, - {file = "fonttools-4.60.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:282dafa55f9659e8999110bd8ed422ebe1c8aecd0dc396550b038e6c9a08b8ea"}, - {file = "fonttools-4.60.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4ba4bd646e86de16160f0fb72e31c3b9b7d0721c3e5b26b9fa2fc931dfdb2652"}, - {file = "fonttools-4.60.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0b0835ed15dd5b40d726bb61c846a688f5b4ce2208ec68779bc81860adb5851a"}, - {file = "fonttools-4.60.1-cp310-cp310-win32.whl", hash = "sha256:1525796c3ffe27bb6268ed2a1bb0dcf214d561dfaf04728abf01489eb5339dce"}, - {file = "fonttools-4.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:268ecda8ca6cb5c4f044b1fb9b3b376e8cd1b361cef275082429dc4174907038"}, - {file = "fonttools-4.60.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7b4c32e232a71f63a5d00259ca3d88345ce2a43295bb049d21061f338124246f"}, - {file = "fonttools-4.60.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3630e86c484263eaac71d117085d509cbcf7b18f677906824e4bace598fb70d2"}, - {file = "fonttools-4.60.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5c1015318e4fec75dd4943ad5f6a206d9727adf97410d58b7e32ab644a807914"}, - {file = "fonttools-4.60.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e6c58beb17380f7c2ea181ea11e7db8c0ceb474c9dd45f48e71e2cb577d146a1"}, - {file = "fonttools-4.60.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec3681a0cb34c255d76dd9d865a55f260164adb9fa02628415cdc2d43ee2c05d"}, - {file = "fonttools-4.60.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f4b5c37a5f40e4d733d3bbaaef082149bee5a5ea3156a785ff64d949bd1353fa"}, - {file = "fonttools-4.60.1-cp311-cp311-win32.whl", hash = "sha256:398447f3d8c0c786cbf1209711e79080a40761eb44b27cdafffb48f52bcec258"}, - {file = "fonttools-4.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:d066ea419f719ed87bc2c99a4a4bfd77c2e5949cb724588b9dd58f3fd90b92bf"}, - {file = "fonttools-4.60.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7b0c6d57ab00dae9529f3faf187f2254ea0aa1e04215cf2f1a8ec277c96661bc"}, - {file = "fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:839565cbf14645952d933853e8ade66a463684ed6ed6c9345d0faf1f0e868877"}, - {file = "fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8177ec9676ea6e1793c8a084a90b65a9f778771998eb919d05db6d4b1c0b114c"}, - {file = "fonttools-4.60.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:996a4d1834524adbb423385d5a629b868ef9d774670856c63c9a0408a3063401"}, - {file = "fonttools-4.60.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a46b2f450bc79e06ef3b6394f0c68660529ed51692606ad7f953fc2e448bc903"}, - {file = "fonttools-4.60.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ec722ee589e89a89f5b7574f5c45604030aa6ae24cb2c751e2707193b466fed"}, - {file = "fonttools-4.60.1-cp312-cp312-win32.whl", hash = "sha256:b2cf105cee600d2de04ca3cfa1f74f1127f8455b71dbad02b9da6ec266e116d6"}, - {file = "fonttools-4.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:992775c9fbe2cf794786fa0ffca7f09f564ba3499b8fe9f2f80bd7197db60383"}, - {file = "fonttools-4.60.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6f68576bb4bbf6060c7ab047b1574a1ebe5c50a17de62830079967b211059ebb"}, - {file = "fonttools-4.60.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:eedacb5c5d22b7097482fa834bda0dafa3d914a4e829ec83cdea2a01f8c813c4"}, - {file = "fonttools-4.60.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b33a7884fabd72bdf5f910d0cf46be50dce86a0362a65cfc746a4168c67eb96c"}, - {file = "fonttools-4.60.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2409d5fb7b55fd70f715e6d34e7a6e4f7511b8ad29a49d6df225ee76da76dd77"}, - {file = "fonttools-4.60.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8651e0d4b3bdeda6602b85fdc2abbefc1b41e573ecb37b6779c4ca50753a199"}, - {file = "fonttools-4.60.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:145daa14bf24824b677b9357c5e44fd8895c2a8f53596e1b9ea3496081dc692c"}, - {file = "fonttools-4.60.1-cp313-cp313-win32.whl", hash = "sha256:2299df884c11162617a66b7c316957d74a18e3758c0274762d2cc87df7bc0272"}, - {file = "fonttools-4.60.1-cp313-cp313-win_amd64.whl", hash = "sha256:a3db56f153bd4c5c2b619ab02c5db5192e222150ce5a1bc10f16164714bc39ac"}, - {file = "fonttools-4.60.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:a884aef09d45ba1206712c7dbda5829562d3fea7726935d3289d343232ecb0d3"}, - {file = "fonttools-4.60.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8a44788d9d91df72d1a5eac49b31aeb887a5f4aab761b4cffc4196c74907ea85"}, - {file = "fonttools-4.60.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e852d9dda9f93ad3651ae1e3bb770eac544ec93c3807888798eccddf84596537"}, - {file = "fonttools-4.60.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:154cb6ee417e417bf5f7c42fe25858c9140c26f647c7347c06f0cc2d47eff003"}, - {file = "fonttools-4.60.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5664fd1a9ea7f244487ac8f10340c4e37664675e8667d6fee420766e0fb3cf08"}, - {file = "fonttools-4.60.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:583b7f8e3c49486e4d489ad1deacfb8d5be54a8ef34d6df824f6a171f8511d99"}, - {file = "fonttools-4.60.1-cp314-cp314-win32.whl", hash = "sha256:66929e2ea2810c6533a5184f938502cfdaea4bc3efb7130d8cc02e1c1b4108d6"}, - {file = "fonttools-4.60.1-cp314-cp314-win_amd64.whl", hash = "sha256:f3d5be054c461d6a2268831f04091dc82753176f6ea06dc6047a5e168265a987"}, - {file = "fonttools-4.60.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b6379e7546ba4ae4b18f8ae2b9bc5960936007a1c0e30b342f662577e8bc3299"}, - {file = "fonttools-4.60.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9d0ced62b59e0430b3690dbc5373df1c2aa7585e9a8ce38eff87f0fd993c5b01"}, - {file = "fonttools-4.60.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:875cb7764708b3132637f6c5fb385b16eeba0f7ac9fa45a69d35e09b47045801"}, - {file = "fonttools-4.60.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a184b2ea57b13680ab6d5fbde99ccef152c95c06746cb7718c583abd8f945ccc"}, - {file = "fonttools-4.60.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:026290e4ec76583881763fac284aca67365e0be9f13a7fb137257096114cb3bc"}, - {file = "fonttools-4.60.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f0e8817c7d1a0c2eedebf57ef9a9896f3ea23324769a9a2061a80fe8852705ed"}, - {file = "fonttools-4.60.1-cp314-cp314t-win32.whl", hash = "sha256:1410155d0e764a4615774e5c2c6fc516259fe3eca5882f034eb9bfdbee056259"}, - {file = "fonttools-4.60.1-cp314-cp314t-win_amd64.whl", hash = "sha256:022beaea4b73a70295b688f817ddc24ed3e3418b5036ffcd5658141184ef0d0c"}, - {file = "fonttools-4.60.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:122e1a8ada290423c493491d002f622b1992b1ab0b488c68e31c413390dc7eb2"}, - {file = "fonttools-4.60.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a140761c4ff63d0cb9256ac752f230460ee225ccef4ad8f68affc723c88e2036"}, - {file = "fonttools-4.60.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eae96373e4b7c9e45d099d7a523444e3554360927225c1cdae221a58a45b856"}, - {file = "fonttools-4.60.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:596ecaca36367027d525b3b426d8a8208169d09edcf8c7506aceb3a38bfb55c7"}, - {file = "fonttools-4.60.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2ee06fc57512144d8b0445194c2da9f190f61ad51e230f14836286470c99f854"}, - {file = "fonttools-4.60.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b42d86938e8dda1cd9a1a87a6d82f1818eaf933348429653559a458d027446da"}, - {file = "fonttools-4.60.1-cp39-cp39-win32.whl", hash = "sha256:8b4eb332f9501cb1cd3d4d099374a1e1306783ff95489a1026bde9eb02ccc34a"}, - {file = "fonttools-4.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:7473a8ed9ed09aeaa191301244a5a9dbe46fe0bf54f9d6cd21d83044c3321217"}, - {file = "fonttools-4.60.1-py3-none-any.whl", hash = "sha256:906306ac7afe2156fcf0042173d6ebbb05416af70f6b370967b47f8f00103bbb"}, - {file = "fonttools-4.60.1.tar.gz", hash = "sha256:ef00af0439ebfee806b25f24c8f92109157ff3fac5731dc7867957812e87b8d9"}, + {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c7db70d57e5e1089a274cbb2b1fd635c9a24de809a231b154965d415d6c6d24"}, + {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5fe9fd43882620017add5eabb781ebfbc6998ee49b35bd7f8f79af1f9f99a958"}, + {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8db08051fc9e7d8bc622f2112511b8107d8f27cd89e2f64ec45e9825e8288da"}, + {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a76d4cb80f41ba94a6691264be76435e5f72f2cb3cab0b092a6212855f71c2f6"}, + {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a13fc8aeb24bad755eea8f7f9d409438eb94e82cf86b08fe77a03fbc8f6a96b1"}, + {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b846a1fcf8beadeb9ea4f44ec5bdde393e2f1569e17d700bfc49cd69bde75881"}, + {file = "fonttools-4.61.1-cp310-cp310-win32.whl", hash = "sha256:78a7d3ab09dc47ac1a363a493e6112d8cabed7ba7caad5f54dbe2f08676d1b47"}, + {file = "fonttools-4.61.1-cp310-cp310-win_amd64.whl", hash = "sha256:eff1ac3cc66c2ac7cda1e64b4e2f3ffef474b7335f92fc3833fc632d595fcee6"}, + {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6604b735bb12fef8e0efd5578c9fb5d3d8532d5001ea13a19cddf295673ee09"}, + {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ce02f38a754f207f2f06557523cd39a06438ba3aafc0639c477ac409fc64e37"}, + {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77efb033d8d7ff233385f30c62c7c79271c8885d5c9657d967ede124671bbdfb"}, + {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:75c1a6dfac6abd407634420c93864a1e274ebc1c7531346d9254c0d8f6ca00f9"}, + {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0de30bfe7745c0d1ffa2b0b7048fb7123ad0d71107e10ee090fa0b16b9452e87"}, + {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58b0ee0ab5b1fc9921eccfe11d1435added19d6494dde14e323f25ad2bc30c56"}, + {file = "fonttools-4.61.1-cp311-cp311-win32.whl", hash = "sha256:f79b168428351d11e10c5aeb61a74e1851ec221081299f4cf56036a95431c43a"}, + {file = "fonttools-4.61.1-cp311-cp311-win_amd64.whl", hash = "sha256:fe2efccb324948a11dd09d22136fe2ac8a97d6c1347cf0b58a911dcd529f66b7"}, + {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e"}, + {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2"}, + {file = "fonttools-4.61.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10d88e55330e092940584774ee5e8a6971b01fc2f4d3466a1d6c158230880796"}, + {file = "fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d"}, + {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8"}, + {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0"}, + {file = "fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261"}, + {file = "fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9"}, + {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c"}, + {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e"}, + {file = "fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5"}, + {file = "fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd"}, + {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3"}, + {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d"}, + {file = "fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c"}, + {file = "fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b"}, + {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd"}, + {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e"}, + {file = "fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c"}, + {file = "fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75"}, + {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063"}, + {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2"}, + {file = "fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c"}, + {file = "fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c"}, + {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa"}, + {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91"}, + {file = "fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19"}, + {file = "fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba"}, + {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7"}, + {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118"}, + {file = "fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5"}, + {file = "fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b"}, + {file = "fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371"}, + {file = "fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69"}, ] [package.extras] -all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0) ; python_version <= \"3.12\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] +all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.45.0)", "unicodedata2 (>=17.0.0) ; python_version <= \"3.14\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] lxml = ["lxml (>=4.0)"] pathops = ["skia-pathops (>=0.5.0)"] plot = ["matplotlib"] -repacker = ["uharfbuzz (>=0.23.0)"] +repacker = ["uharfbuzz (>=0.45.0)"] symfont = ["sympy"] type1 = ["xattr ; sys_platform == \"darwin\""] -unicode = ["unicodedata2 (>=15.1.0) ; python_version <= \"3.12\""] +unicode = ["unicodedata2 (>=17.0.0) ; python_version <= \"3.14\""] woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] [[package]] @@ -1156,15 +1220,15 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "importlib-metadata" -version = "8.5.0" +version = "8.7.1" description = "Read metadata from Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] markers = "python_version == \"3.9\"" files = [ - {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, - {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, + {file = "importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151"}, + {file = "importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb"}, ] [package.dependencies] @@ -1174,22 +1238,22 @@ zipp = ">=3.20" check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] +enabler = ["pytest-enabler (>=3.4)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] -type = ["pytest-mypy"] +test = ["flufl.flake8", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["mypy (<1.19) ; platform_python_implementation == \"PyPy\"", "pytest-mypy (>=1.0.1)"] [[package]] name = "importlib-resources" -version = "6.4.5" +version = "6.5.2" description = "Read resources from Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main", "examples"] markers = "python_version == \"3.9\"" files = [ - {file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"}, - {file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"}, + {file = "importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec"}, + {file = "importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c"}, ] [package.dependencies] @@ -1265,56 +1329,54 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0,<9)", "pytest-async [[package]] name = "ipython" -version = "8.12.3" +version = "8.18.1" description = "IPython: Productive Interactive Computing" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] markers = "python_version < \"3.11\"" files = [ - {file = "ipython-8.12.3-py3-none-any.whl", hash = "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c"}, - {file = "ipython-8.12.3.tar.gz", hash = "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363"}, + {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, + {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, ] [package.dependencies] -appnope = {version = "*", markers = "sys_platform == \"darwin\""} -backcall = "*" colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -pickleshare = "*" -prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +prompt-toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack-data = "*" traitlets = ">=5" typing-extensions = {version = "*", markers = "python_version < \"3.10\""} [package.extras] -all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] black = ["black"] -doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] +test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] [[package]] name = "ipython" -version = "8.37.0" +version = "8.38.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" groups = ["dev"] markers = "python_version >= \"3.11\"" files = [ - {file = "ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2"}, - {file = "ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216"}, + {file = "ipython-8.38.0-py3-none-any.whl", hash = "sha256:750162629d800ac65bb3b543a14e7a74b0e88063eac9b92124d4b2aa3f6d8e86"}, + {file = "ipython-8.38.0.tar.gz", hash = "sha256:9cfea8c903ce0867cc2f23199ed8545eb741f3a69420bfcf3743ad1cec856d39"}, ] [package.dependencies] @@ -1345,14 +1407,14 @@ test-extra = ["curio", "ipython[test]", "jupyter_ai", "matplotlib (!=3.2.0)", "n [[package]] name = "ipywidgets" -version = "8.1.7" +version = "8.1.8" description = "Jupyter interactive widgets" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ipywidgets-8.1.7-py3-none-any.whl", hash = "sha256:764f2602d25471c213919b8a1997df04bef869251db4ca8efba1b76b1bd9f7bb"}, - {file = "ipywidgets-8.1.7.tar.gz", hash = "sha256:15f1ac050b9ccbefd45dccfbb2ef6bed0029d8278682d569d71b8dd96bee0376"}, + {file = "ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e"}, + {file = "ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668"}, ] [package.dependencies] @@ -1420,19 +1482,16 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "json5" -version = "0.12.1" +version = "0.13.0" description = "A Python implementation of the JSON5 data format." optional = false python-versions = ">=3.8.0" groups = ["dev"] files = [ - {file = "json5-0.12.1-py3-none-any.whl", hash = "sha256:d9c9b3bc34a5f54d43c35e11ef7cb87d8bdd098c6ace87117a7b7e83e705c1d5"}, - {file = "json5-0.12.1.tar.gz", hash = "sha256:b2743e77b3242f8d03c143dd975a6ec7c52e2f2afe76ed934e53503dd4ad4990"}, + {file = "json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc"}, + {file = "json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf"}, ] -[package.extras] -dev = ["build (==1.2.2.post1)", "coverage (==7.5.4) ; python_version < \"3.9\"", "coverage (==7.8.0) ; python_version >= \"3.9\"", "mypy (==1.14.1) ; python_version < \"3.9\"", "mypy (==1.15.0) ; python_version >= \"3.9\"", "pip (==25.0.1)", "pylint (==3.2.7) ; python_version < \"3.9\"", "pylint (==3.3.6) ; python_version >= \"3.9\"", "ruff (==0.11.2)", "twine (==6.1.0)", "uv (==0.6.11)"] - [[package]] name = "jsonpointer" version = "3.0.0" @@ -1518,6 +1577,7 @@ description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.8" groups = ["dev"] +markers = "python_version < \"3.11\"" files = [ {file = "jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f"}, {file = "jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419"}, @@ -1535,6 +1595,30 @@ traitlets = ">=5.3" docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko ; sys_platform == \"win32\"", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] +[[package]] +name = "jupyter-client" +version = "8.7.0" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "jupyter_client-8.7.0-py3-none-any.whl", hash = "sha256:3671a94fd25e62f5f2f554f5e95389c2294d89822378a5f2dd24353e1494a9e0"}, + {file = "jupyter_client-8.7.0.tar.gz", hash = "sha256:3357212d9cbe01209e59190f67a3a7e1f387a4f4e88d1e0433ad84d7b262531d"}, +] + +[package.dependencies] +jupyter-core = ">=5.1" +python-dateutil = ">=2.8.2" +pyzmq = ">=25.0" +tornado = ">=6.4.1" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["anyio", "coverage", "ipykernel (>=6.14)", "mypy", "paramiko ; sys_platform == \"win32\"", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.6.2)", "pytest-timeout"] + [[package]] name = "jupyter-console" version = "6.6.3" @@ -1705,14 +1789,14 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.4.10" +version = "4.5.1" description = "JupyterLab computational environment" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "jupyterlab-4.4.10-py3-none-any.whl", hash = "sha256:65939ab4c8dcd0c42185c2d0d1a9d60b254dc8c46fc4fdb286b63c51e9358e07"}, - {file = "jupyterlab-4.4.10.tar.gz", hash = "sha256:521c017508af4e1d6d9d8a9d90f47a11c61197ad63b2178342489de42540a615"}, + {file = "jupyterlab-4.5.1-py3-none-any.whl", hash = "sha256:31b059de96de0754ff1f2ce6279774b6aab8c34d7082e9752db58207c99bd514"}, + {file = "jupyterlab-4.5.1.tar.gz", hash = "sha256:09da1ddfbd9eec18b5101dbb8515612aa1e47443321fb99503725a88e93d20d9"}, ] [package.dependencies] @@ -1724,7 +1808,7 @@ jinja2 = ">=3.0.3" jupyter-core = "*" jupyter-lsp = ">=2.0.0" jupyter-server = ">=2.4.0,<3" -jupyterlab-server = ">=2.27.1,<3" +jupyterlab-server = ">=2.28.0,<3" notebook-shim = ">=0.2" packaging = "*" setuptools = ">=41.1.0" @@ -1733,9 +1817,9 @@ tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.11.4)"] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.11.12)"] docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<8.2.0)", "sphinx-copybutton"] -docs-screenshots = ["altair (==5.5.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.5)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.3.post1)", "matplotlib (==3.10.0)", "nbconvert (>=7.0.0)", "pandas (==2.2.3)", "scipy (==1.15.1)", "vega-datasets (==0.9.0)"] +docs-screenshots = ["altair (==6.0.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.5)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.3.post1)", "matplotlib (==3.10.0)", "nbconvert (>=7.0.0)", "pandas (==2.2.3)", "scipy (==1.15.1)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] upgrade-extension = ["copier (>=9,<10)", "jinja2-time (<0.3)", "pydantic (<3.0)", "pyyaml-include (<3.0)", "tomli-w (<2.0)"] @@ -1780,14 +1864,14 @@ test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-v [[package]] name = "jupyterlab-widgets" -version = "3.0.15" +version = "3.0.16" description = "Jupyter interactive widgets for JupyterLab" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "jupyterlab_widgets-3.0.15-py3-none-any.whl", hash = "sha256:d59023d7d7ef71400d51e6fee9a88867f6e65e10a4201605d2d7f3e8f012a31c"}, - {file = "jupyterlab_widgets-3.0.15.tar.gz", hash = "sha256:2920888a0c2922351a9202817957a68c07d99673504d6cd37345299e971bb08b"}, + {file = "jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8"}, + {file = "jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0"}, ] [[package]] @@ -2045,6 +2129,93 @@ interegular = ["interegular (>=0.3.1,<0.4.0)"] nearley = ["js2py"] regex = ["regex"] +[[package]] +name = "librt" +version = "0.7.7" +description = "Mypyc runtime library" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "platform_python_implementation != \"PyPy\"" +files = [ + {file = "librt-0.7.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4836c5645f40fbdc275e5670819bde5ab5f2e882290d304e3c6ddab1576a6d0"}, + {file = "librt-0.7.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae8aec43117a645a31e5f60e9e3a0797492e747823b9bda6972d521b436b4e8"}, + {file = "librt-0.7.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:aea05f701ccd2a76b34f0daf47ca5068176ff553510b614770c90d76ac88df06"}, + {file = "librt-0.7.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b16ccaeff0ed4355dfb76fe1ea7a5d6d03b5ad27f295f77ee0557bc20a72495"}, + {file = "librt-0.7.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c48c7e150c095d5e3cea7452347ba26094be905d6099d24f9319a8b475fcd3e0"}, + {file = "librt-0.7.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4dcee2f921a8632636d1c37f1bbdb8841d15666d119aa61e5399c5268e7ce02e"}, + {file = "librt-0.7.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:14ef0f4ac3728ffd85bfc58e2f2f48fb4ef4fa871876f13a73a7381d10a9f77c"}, + {file = "librt-0.7.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e4ab69fa37f8090f2d971a5d2bc606c7401170dbdae083c393d6cbf439cb45b8"}, + {file = "librt-0.7.7-cp310-cp310-win32.whl", hash = "sha256:4bf3cc46d553693382d2abf5f5bd493d71bb0f50a7c0beab18aa13a5545c8900"}, + {file = "librt-0.7.7-cp310-cp310-win_amd64.whl", hash = "sha256:f0c8fe5aeadd8a0e5b0598f8a6ee3533135ca50fd3f20f130f9d72baf5c6ac58"}, + {file = "librt-0.7.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a487b71fbf8a9edb72a8c7a456dda0184642d99cd007bc819c0b7ab93676a8ee"}, + {file = "librt-0.7.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f4d4efb218264ecf0f8516196c9e2d1a0679d9fb3bb15df1155a35220062eba8"}, + {file = "librt-0.7.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b8bb331aad734b059c4b450cd0a225652f16889e286b2345af5e2c3c625c3d85"}, + {file = "librt-0.7.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:467dbd7443bda08338fc8ad701ed38cef48194017554f4c798b0a237904b3f99"}, + {file = "librt-0.7.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50d1d1ee813d2d1a3baf2873634ba506b263032418d16287c92ec1cc9c1a00cb"}, + {file = "librt-0.7.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c7e5070cf3ec92d98f57574da0224f8c73faf1ddd6d8afa0b8c9f6e86997bc74"}, + {file = "librt-0.7.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bdb9f3d865b2dafe7f9ad7f30ef563c80d0ddd2fdc8cc9b8e4f242f475e34d75"}, + {file = "librt-0.7.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8185c8497d45164e256376f9da5aed2bb26ff636c798c9dabe313b90e9f25b28"}, + {file = "librt-0.7.7-cp311-cp311-win32.whl", hash = "sha256:44d63ce643f34a903f09ff7ca355aae019a3730c7afd6a3c037d569beeb5d151"}, + {file = "librt-0.7.7-cp311-cp311-win_amd64.whl", hash = "sha256:7d13cc340b3b82134f8038a2bfe7137093693dcad8ba5773da18f95ad6b77a8a"}, + {file = "librt-0.7.7-cp311-cp311-win_arm64.whl", hash = "sha256:983de36b5a83fe9222f4f7dcd071f9b1ac6f3f17c0af0238dadfb8229588f890"}, + {file = "librt-0.7.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2a85a1fc4ed11ea0eb0a632459ce004a2d14afc085a50ae3463cd3dfe1ce43fc"}, + {file = "librt-0.7.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c87654e29a35938baead1c4559858f346f4a2a7588574a14d784f300ffba0efd"}, + {file = "librt-0.7.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c9faaebb1c6212c20afd8043cd6ed9de0a47d77f91a6b5b48f4e46ed470703fe"}, + {file = "librt-0.7.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1908c3e5a5ef86b23391448b47759298f87f997c3bd153a770828f58c2bb4630"}, + {file = "librt-0.7.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbc4900e95a98fc0729523be9d93a8fedebb026f32ed9ffc08acd82e3e181503"}, + {file = "librt-0.7.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a7ea4e1fbd253e5c68ea0fe63d08577f9d288a73f17d82f652ebc61fa48d878d"}, + {file = "librt-0.7.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ef7699b7a5a244b1119f85c5bbc13f152cd38240cbb2baa19b769433bae98e50"}, + {file = "librt-0.7.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:955c62571de0b181d9e9e0a0303c8bc90d47670a5eff54cf71bf5da61d1899cf"}, + {file = "librt-0.7.7-cp312-cp312-win32.whl", hash = "sha256:1bcd79be209313b270b0e1a51c67ae1af28adad0e0c7e84c3ad4b5cb57aaa75b"}, + {file = "librt-0.7.7-cp312-cp312-win_amd64.whl", hash = "sha256:4353ee891a1834567e0302d4bd5e60f531912179578c36f3d0430f8c5e16b456"}, + {file = "librt-0.7.7-cp312-cp312-win_arm64.whl", hash = "sha256:a76f1d679beccccdf8c1958e732a1dfcd6e749f8821ee59d7bec009ac308c029"}, + {file = "librt-0.7.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f4a0b0a3c86ba9193a8e23bb18f100d647bf192390ae195d84dfa0a10fb6244"}, + {file = "librt-0.7.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5335890fea9f9e6c4fdf8683061b9ccdcbe47c6dc03ab8e9b68c10acf78be78d"}, + {file = "librt-0.7.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9b4346b1225be26def3ccc6c965751c74868f0578cbcba293c8ae9168483d811"}, + {file = "librt-0.7.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a10b8eebdaca6e9fdbaf88b5aefc0e324b763a5f40b1266532590d5afb268a4c"}, + {file = "librt-0.7.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:067be973d90d9e319e6eb4ee2a9b9307f0ecd648b8a9002fa237289a4a07a9e7"}, + {file = "librt-0.7.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:23d2299ed007812cccc1ecef018db7d922733382561230de1f3954db28433977"}, + {file = "librt-0.7.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6b6f8ea465524aa4c7420c7cc4ca7d46fe00981de8debc67b1cc2e9957bb5b9d"}, + {file = "librt-0.7.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8df32a99cc46eb0ee90afd9ada113ae2cafe7e8d673686cf03ec53e49635439"}, + {file = "librt-0.7.7-cp313-cp313-win32.whl", hash = "sha256:86f86b3b785487c7760247bcdac0b11aa8bf13245a13ed05206286135877564b"}, + {file = "librt-0.7.7-cp313-cp313-win_amd64.whl", hash = "sha256:4862cb2c702b1f905c0503b72d9d4daf65a7fdf5a9e84560e563471e57a56949"}, + {file = "librt-0.7.7-cp313-cp313-win_arm64.whl", hash = "sha256:0996c83b1cb43c00e8c87835a284f9057bc647abd42b5871e5f941d30010c832"}, + {file = "librt-0.7.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:23daa1ab0512bafdd677eb1bfc9611d8ffbe2e328895671e64cb34166bc1b8c8"}, + {file = "librt-0.7.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:558a9e5a6f3cc1e20b3168fb1dc802d0d8fa40731f6e9932dcc52bbcfbd37111"}, + {file = "librt-0.7.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2567cb48dc03e5b246927ab35cbb343376e24501260a9b5e30b8e255dca0d1d2"}, + {file = "librt-0.7.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6066c638cdf85ff92fc6f932d2d73c93a0e03492cdfa8778e6d58c489a3d7259"}, + {file = "librt-0.7.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a609849aca463074c17de9cda173c276eb8fee9e441053529e7b9e249dc8b8ee"}, + {file = "librt-0.7.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:add4e0a000858fe9bb39ed55f31085506a5c38363e6eb4a1e5943a10c2bfc3d1"}, + {file = "librt-0.7.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a3bfe73a32bd0bdb9a87d586b05a23c0a1729205d79df66dee65bb2e40d671ba"}, + {file = "librt-0.7.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:0ecce0544d3db91a40f8b57ae26928c02130a997b540f908cefd4d279d6c5848"}, + {file = "librt-0.7.7-cp314-cp314-win32.whl", hash = "sha256:8f7a74cf3a80f0c3b0ec75b0c650b2f0a894a2cec57ef75f6f72c1e82cdac61d"}, + {file = "librt-0.7.7-cp314-cp314-win_amd64.whl", hash = "sha256:3d1fe2e8df3268dd6734dba33ededae72ad5c3a859b9577bc00b715759c5aaab"}, + {file = "librt-0.7.7-cp314-cp314-win_arm64.whl", hash = "sha256:2987cf827011907d3dfd109f1be0d61e173d68b1270107bb0e89f2fca7f2ed6b"}, + {file = "librt-0.7.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8e92c8de62b40bfce91d5e12c6e8b15434da268979b1af1a6589463549d491e6"}, + {file = "librt-0.7.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f683dcd49e2494a7535e30f779aa1ad6e3732a019d80abe1309ea91ccd3230e3"}, + {file = "librt-0.7.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9b15e5d17812d4d629ff576699954f74e2cc24a02a4fc401882dd94f81daba45"}, + {file = "librt-0.7.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c084841b879c4d9b9fa34e5d5263994f21aea7fd9c6add29194dbb41a6210536"}, + {file = "librt-0.7.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10c8fb9966f84737115513fecbaf257f9553d067a7dd45a69c2c7e5339e6a8dc"}, + {file = "librt-0.7.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9b5fb1ecb2c35362eab2dbd354fd1efa5a8440d3e73a68be11921042a0edc0ff"}, + {file = "librt-0.7.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d1454899909d63cc9199a89fcc4f81bdd9004aef577d4ffc022e600c412d57f3"}, + {file = "librt-0.7.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7ef28f2e7a016b29792fe0a2dd04dec75725b32a1264e390c366103f834a9c3a"}, + {file = "librt-0.7.7-cp314-cp314t-win32.whl", hash = "sha256:5e419e0db70991b6ba037b70c1d5bbe92b20ddf82f31ad01d77a347ed9781398"}, + {file = "librt-0.7.7-cp314-cp314t-win_amd64.whl", hash = "sha256:d6b7d93657332c817b8d674ef6bf1ab7796b4f7ce05e420fd45bd258a72ac804"}, + {file = "librt-0.7.7-cp314-cp314t-win_arm64.whl", hash = "sha256:142c2cd91794b79fd0ce113bd658993b7ede0fe93057668c2f98a45ca00b7e91"}, + {file = "librt-0.7.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c8ffe3431d98cc043a14e88b21288b5ec7ee12cb01260e94385887f285ef9389"}, + {file = "librt-0.7.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e40d20ae1722d6b8ea6acf4597e789604649dcd9c295eb7361a28225bc2e9e12"}, + {file = "librt-0.7.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f2cb63c49bc96847c3bb8dca350970e4dcd19936f391cfdfd057dcb37c4fa97e"}, + {file = "librt-0.7.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f2f8dcf5ab9f80fb970c6fd780b398efb2f50c1962485eb8d3ab07788595a48"}, + {file = "librt-0.7.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1f5cc41a570269d1be7a676655875e3a53de4992a9fa38efb7983e97cf73d7c"}, + {file = "librt-0.7.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff1fb2dfef035549565a4124998fadcb7a3d4957131ddf004a56edeb029626b3"}, + {file = "librt-0.7.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ab2a2a9cd7d044e1a11ca64a86ad3361d318176924bbe5152fbc69f99be20b8c"}, + {file = "librt-0.7.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad3fc2d859a709baf9dd9607bb72f599b1cfb8a39eafd41307d0c3c4766763cb"}, + {file = "librt-0.7.7-cp39-cp39-win32.whl", hash = "sha256:f83c971eb9d2358b6a18da51dc0ae00556ac7c73104dde16e9e14c15aaf685ca"}, + {file = "librt-0.7.7-cp39-cp39-win_amd64.whl", hash = "sha256:264720fc288c86039c091a4ad63419a5d7cabbf1c1c9933336a957ed2483e570"}, + {file = "librt-0.7.7.tar.gz", hash = "sha256:81d957b069fed1890953c3b9c3895c7689960f233eea9a1d9607f71ce7f00b2c"}, +] + [[package]] name = "markupsafe" version = "3.0.3" @@ -2213,68 +2384,68 @@ dev = ["meson-python (>=0.13.1,<0.17.0)", "numpy (>=1.25)", "pybind11 (>=2.6,!=2 [[package]] name = "matplotlib" -version = "3.10.7" +version = "3.10.8" description = "Python plotting package" optional = false python-versions = ">=3.10" groups = ["main", "examples"] markers = "python_version >= \"3.11\"" files = [ - {file = "matplotlib-3.10.7-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ac81eee3b7c266dd92cee1cd658407b16c57eed08c7421fa354ed68234de380"}, - {file = "matplotlib-3.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:667ecd5d8d37813a845053d8f5bf110b534c3c9f30e69ebd25d4701385935a6d"}, - {file = "matplotlib-3.10.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc1c51b846aca49a5a8b44fbba6a92d583a35c64590ad9e1e950dc88940a4297"}, - {file = "matplotlib-3.10.7-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a11c2e9e72e7de09b7b72e62f3df23317c888299c875e2b778abf1eda8c0a42"}, - {file = "matplotlib-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f19410b486fdd139885ace124e57f938c1e6a3210ea13dd29cab58f5d4bc12c7"}, - {file = "matplotlib-3.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:b498e9e4022f93de2d5a37615200ca01297ceebbb56fe4c833f46862a490f9e3"}, - {file = "matplotlib-3.10.7-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:53b492410a6cd66c7a471de6c924f6ede976e963c0f3097a3b7abfadddc67d0a"}, - {file = "matplotlib-3.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d9749313deb729f08207718d29c86246beb2ea3fdba753595b55901dee5d2fd6"}, - {file = "matplotlib-3.10.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2222c7ba2cbde7fe63032769f6eb7e83ab3227f47d997a8453377709b7fe3a5a"}, - {file = "matplotlib-3.10.7-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e91f61a064c92c307c5a9dc8c05dc9f8a68f0a3be199d9a002a0622e13f874a1"}, - {file = "matplotlib-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f1851eab59ca082c95df5a500106bad73672645625e04538b3ad0f69471ffcc"}, - {file = "matplotlib-3.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:6516ce375109c60ceec579e699524e9d504cd7578506f01150f7a6bc174a775e"}, - {file = "matplotlib-3.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:b172db79759f5f9bc13ef1c3ef8b9ee7b37b0247f987fbbbdaa15e4f87fd46a9"}, - {file = "matplotlib-3.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7a0edb7209e21840e8361e91ea84ea676658aa93edd5f8762793dec77a4a6748"}, - {file = "matplotlib-3.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c380371d3c23e0eadf8ebff114445b9f970aff2010198d498d4ab4c3b41eea4f"}, - {file = "matplotlib-3.10.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d5f256d49fea31f40f166a5e3131235a5d2f4b7f44520b1cf0baf1ce568ccff0"}, - {file = "matplotlib-3.10.7-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11ae579ac83cdf3fb72573bb89f70e0534de05266728740d478f0f818983c695"}, - {file = "matplotlib-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4c14b6acd16cddc3569a2d515cfdd81c7a68ac5639b76548cfc1a9e48b20eb65"}, - {file = "matplotlib-3.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:0d8c32b7ea6fb80b1aeff5a2ceb3fb9778e2759e899d9beff75584714afcc5ee"}, - {file = "matplotlib-3.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:5f3f6d315dcc176ba7ca6e74c7768fb7e4cf566c49cb143f6bc257b62e634ed8"}, - {file = "matplotlib-3.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1d9d3713a237970569156cfb4de7533b7c4eacdd61789726f444f96a0d28f57f"}, - {file = "matplotlib-3.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37a1fea41153dd6ee061d21ab69c9cf2cf543160b1b85d89cd3d2e2a7902ca4c"}, - {file = "matplotlib-3.10.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b3c4ea4948d93c9c29dc01c0c23eef66f2101bf75158c291b88de6525c55c3d1"}, - {file = "matplotlib-3.10.7-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22df30ffaa89f6643206cf13877191c63a50e8f800b038bc39bee9d2d4957632"}, - {file = "matplotlib-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b69676845a0a66f9da30e87f48be36734d6748024b525ec4710be40194282c84"}, - {file = "matplotlib-3.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:744991e0cc863dd669c8dc9136ca4e6e0082be2070b9d793cbd64bec872a6815"}, - {file = "matplotlib-3.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:fba2974df0bf8ce3c995fa84b79cde38326e0f7b5409e7a3a481c1141340bcf7"}, - {file = "matplotlib-3.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:932c55d1fa7af4423422cb6a492a31cbcbdbe68fd1a9a3f545aa5e7a143b5355"}, - {file = "matplotlib-3.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e38c2d581d62ee729a6e144c47a71b3f42fb4187508dbbf4fe71d5612c3433b"}, - {file = "matplotlib-3.10.7-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:786656bb13c237bbcebcd402f65f44dd61ead60ee3deb045af429d889c8dbc67"}, - {file = "matplotlib-3.10.7-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09d7945a70ea43bf9248f4b6582734c2fe726723204a76eca233f24cffc7ef67"}, - {file = "matplotlib-3.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d0b181e9fa8daf1d9f2d4c547527b167cb8838fc587deabca7b5c01f97199e84"}, - {file = "matplotlib-3.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:31963603041634ce1a96053047b40961f7a29eb8f9a62e80cc2c0427aa1d22a2"}, - {file = "matplotlib-3.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:aebed7b50aa6ac698c90f60f854b47e48cd2252b30510e7a1feddaf5a3f72cbf"}, - {file = "matplotlib-3.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d883460c43e8c6b173fef244a2341f7f7c0e9725c7fe68306e8e44ed9c8fb100"}, - {file = "matplotlib-3.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07124afcf7a6504eafcb8ce94091c5898bbdd351519a1beb5c45f7a38c67e77f"}, - {file = "matplotlib-3.10.7-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c17398b709a6cce3d9fdb1595c33e356d91c098cd9486cb2cc21ea2ea418e715"}, - {file = "matplotlib-3.10.7-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7146d64f561498764561e9cd0ed64fcf582e570fc519e6f521e2d0cfd43365e1"}, - {file = "matplotlib-3.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:90ad854c0a435da3104c01e2c6f0028d7e719b690998a2333d7218db80950722"}, - {file = "matplotlib-3.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:4645fc5d9d20ffa3a39361fcdbcec731382763b623b72627806bf251b6388866"}, - {file = "matplotlib-3.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:9257be2f2a03415f9105c486d304a321168e61ad450f6153d77c69504ad764bb"}, - {file = "matplotlib-3.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1e4bbad66c177a8fdfa53972e5ef8be72a5f27e6a607cec0d8579abd0f3102b1"}, - {file = "matplotlib-3.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d8eb7194b084b12feb19142262165832fc6ee879b945491d1c3d4660748020c4"}, - {file = "matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4d41379b05528091f00e1728004f9a8d7191260f3862178b88e8fd770206318"}, - {file = "matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a74f79fafb2e177f240579bc83f0b60f82cc47d2f1d260f422a0627207008ca"}, - {file = "matplotlib-3.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:702590829c30aada1e8cef0568ddbffa77ca747b4d6e36c6d173f66e301f89cc"}, - {file = "matplotlib-3.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:f79d5de970fc90cd5591f60053aecfce1fcd736e0303d9f0bf86be649fa68fb8"}, - {file = "matplotlib-3.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:cb783436e47fcf82064baca52ce748af71725d0352e1d31564cbe9c95df92b9c"}, - {file = "matplotlib-3.10.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5c09cf8f2793f81368f49f118b6f9f937456362bee282eac575cca7f84cda537"}, - {file = "matplotlib-3.10.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:de66744b2bb88d5cd27e80dfc2ec9f0517d0a46d204ff98fe9e5f2864eb67657"}, - {file = "matplotlib-3.10.7-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:53cc80662dd197ece414dd5b66e07370201515a3eaf52e7c518c68c16814773b"}, - {file = "matplotlib-3.10.7-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:15112bcbaef211bd663fa935ec33313b948e214454d949b723998a43357b17b0"}, - {file = "matplotlib-3.10.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d2a959c640cdeecdd2ec3136e8ea0441da59bcaf58d67e9c590740addba2cb68"}, - {file = "matplotlib-3.10.7-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3886e47f64611046bc1db523a09dd0a0a6bed6081e6f90e13806dd1d1d1b5e91"}, - {file = "matplotlib-3.10.7.tar.gz", hash = "sha256:a06ba7e2a2ef9131c79c49e63dad355d2d878413a0376c1727c8b9335ff731c7"}, + {file = "matplotlib-3.10.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:00270d217d6b20d14b584c521f810d60c5c78406dc289859776550df837dcda7"}, + {file = "matplotlib-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b3c1cc42aa184b3f738cfa18c1c1d72fd496d85467a6cf7b807936d39aa656"}, + {file = "matplotlib-3.10.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee40c27c795bda6a5292e9cff9890189d32f7e3a0bf04e0e3c9430c4a00c37df"}, + {file = "matplotlib-3.10.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a48f2b74020919552ea25d222d5cc6af9ca3f4eb43a93e14d068457f545c2a17"}, + {file = "matplotlib-3.10.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f254d118d14a7f99d616271d6c3c27922c092dac11112670b157798b89bf4933"}, + {file = "matplotlib-3.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:f9b587c9c7274c1613a30afabf65a272114cd6cdbe67b3406f818c79d7ab2e2a"}, + {file = "matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160"}, + {file = "matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78"}, + {file = "matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4"}, + {file = "matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2"}, + {file = "matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6"}, + {file = "matplotlib-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9"}, + {file = "matplotlib-3.10.8-cp311-cp311-win_arm64.whl", hash = "sha256:bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2"}, + {file = "matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a"}, + {file = "matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58"}, + {file = "matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04"}, + {file = "matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f"}, + {file = "matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466"}, + {file = "matplotlib-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf"}, + {file = "matplotlib-3.10.8-cp312-cp312-win_arm64.whl", hash = "sha256:3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b"}, + {file = "matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6"}, + {file = "matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1"}, + {file = "matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486"}, + {file = "matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce"}, + {file = "matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6"}, + {file = "matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149"}, + {file = "matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645"}, + {file = "matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077"}, + {file = "matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22"}, + {file = "matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39"}, + {file = "matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565"}, + {file = "matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a"}, + {file = "matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958"}, + {file = "matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5"}, + {file = "matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f"}, + {file = "matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b"}, + {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d"}, + {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008"}, + {file = "matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c"}, + {file = "matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11"}, + {file = "matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8"}, + {file = "matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50"}, + {file = "matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908"}, + {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a"}, + {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1"}, + {file = "matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c"}, + {file = "matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b"}, + {file = "matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f"}, + {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f97aeb209c3d2511443f8797e3e5a569aebb040d4f8bc79aa3ee78a8fb9e3dd8"}, + {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fb061f596dad3a0f52b60dc6a5dec4a0c300dec41e058a7efe09256188d170b7"}, + {file = "matplotlib-3.10.8-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12d90df9183093fcd479f4172ac26b322b1248b15729cb57f42f71f24c7e37a3"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a"}, + {file = "matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2"}, + {file = "matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3"}, ] [package.dependencies] @@ -2311,14 +2482,14 @@ test = ["flake8", "nbdime", "nbval", "notebook", "pytest"] [[package]] name = "mistune" -version = "3.1.4" +version = "3.2.0" description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "mistune-3.1.4-py3-none-any.whl", hash = "sha256:93691da911e5d9d2e23bc54472892aff676df27a75274962ff9edc210364266d"}, - {file = "mistune-3.1.4.tar.gz", hash = "sha256:b5a7f801d389f724ec702840c11d8fc48f2b33519102fc7ee739e8177b672164"}, + {file = "mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1"}, + {file = "mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a"}, ] [package.dependencies] @@ -2358,53 +2529,54 @@ dill = ">=0.4.0" [[package]] name = "mypy" -version = "1.18.2" +version = "1.19.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy-1.18.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eab0cf6294dafe397c261a75f96dc2c31bffe3b944faa24db5def4e2b0f77c"}, - {file = "mypy-1.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a780ca61fc239e4865968ebc5240bb3bf610ef59ac398de9a7421b54e4a207e"}, - {file = "mypy-1.18.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:448acd386266989ef11662ce3c8011fd2a7b632e0ec7d61a98edd8e27472225b"}, - {file = "mypy-1.18.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9e171c465ad3901dc652643ee4bffa8e9fef4d7d0eece23b428908c77a76a66"}, - {file = "mypy-1.18.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:592ec214750bc00741af1f80cbf96b5013d81486b7bb24cb052382c19e40b428"}, - {file = "mypy-1.18.2-cp310-cp310-win_amd64.whl", hash = "sha256:7fb95f97199ea11769ebe3638c29b550b5221e997c63b14ef93d2e971606ebed"}, - {file = "mypy-1.18.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:807d9315ab9d464125aa9fcf6d84fde6e1dc67da0b6f80e7405506b8ac72bc7f"}, - {file = "mypy-1.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:776bb00de1778caf4db739c6e83919c1d85a448f71979b6a0edd774ea8399341"}, - {file = "mypy-1.18.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1379451880512ffce14505493bd9fe469e0697543717298242574882cf8cdb8d"}, - {file = "mypy-1.18.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1331eb7fd110d60c24999893320967594ff84c38ac6d19e0a76c5fd809a84c86"}, - {file = "mypy-1.18.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ca30b50a51e7ba93b00422e486cbb124f1c56a535e20eff7b2d6ab72b3b2e37"}, - {file = "mypy-1.18.2-cp311-cp311-win_amd64.whl", hash = "sha256:664dc726e67fa54e14536f6e1224bcfce1d9e5ac02426d2326e2bb4e081d1ce8"}, - {file = "mypy-1.18.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:33eca32dd124b29400c31d7cf784e795b050ace0e1f91b8dc035672725617e34"}, - {file = "mypy-1.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3c47adf30d65e89b2dcd2fa32f3aeb5e94ca970d2c15fcb25e297871c8e4764"}, - {file = "mypy-1.18.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d6c838e831a062f5f29d11c9057c6009f60cb294fea33a98422688181fe2893"}, - {file = "mypy-1.18.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01199871b6110a2ce984bde85acd481232d17413868c9807e95c1b0739a58914"}, - {file = "mypy-1.18.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a2afc0fa0b0e91b4599ddfe0f91e2c26c2b5a5ab263737e998d6817874c5f7c8"}, - {file = "mypy-1.18.2-cp312-cp312-win_amd64.whl", hash = "sha256:d8068d0afe682c7c4897c0f7ce84ea77f6de953262b12d07038f4d296d547074"}, - {file = "mypy-1.18.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:07b8b0f580ca6d289e69209ec9d3911b4a26e5abfde32228a288eb79df129fcc"}, - {file = "mypy-1.18.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ed4482847168439651d3feee5833ccedbf6657e964572706a2adb1f7fa4dfe2e"}, - {file = "mypy-1.18.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3ad2afadd1e9fea5cf99a45a822346971ede8685cc581ed9cd4d42eaf940986"}, - {file = "mypy-1.18.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a431a6f1ef14cf8c144c6b14793a23ec4eae3db28277c358136e79d7d062f62d"}, - {file = "mypy-1.18.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7ab28cc197f1dd77a67e1c6f35cd1f8e8b73ed2217e4fc005f9e6a504e46e7ba"}, - {file = "mypy-1.18.2-cp313-cp313-win_amd64.whl", hash = "sha256:0e2785a84b34a72ba55fb5daf079a1003a34c05b22238da94fcae2bbe46f3544"}, - {file = "mypy-1.18.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:62f0e1e988ad41c2a110edde6c398383a889d95b36b3e60bcf155f5164c4fdce"}, - {file = "mypy-1.18.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8795a039bab805ff0c1dfdb8cd3344642c2b99b8e439d057aba30850b8d3423d"}, - {file = "mypy-1.18.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ca1e64b24a700ab5ce10133f7ccd956a04715463d30498e64ea8715236f9c9c"}, - {file = "mypy-1.18.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d924eef3795cc89fecf6bedc6ed32b33ac13e8321344f6ddbf8ee89f706c05cb"}, - {file = "mypy-1.18.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20c02215a080e3a2be3aa50506c67242df1c151eaba0dcbc1e4e557922a26075"}, - {file = "mypy-1.18.2-cp314-cp314-win_amd64.whl", hash = "sha256:749b5f83198f1ca64345603118a6f01a4e99ad4bf9d103ddc5a3200cc4614adf"}, - {file = "mypy-1.18.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25a9c8fb67b00599f839cf472713f54249a62efd53a54b565eb61956a7e3296b"}, - {file = "mypy-1.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2b9c7e284ee20e7598d6f42e13ca40b4928e6957ed6813d1ab6348aa3f47133"}, - {file = "mypy-1.18.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6985ed057513e344e43a26cc1cd815c7a94602fb6a3130a34798625bc2f07b6"}, - {file = "mypy-1.18.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f27105f1525ec024b5c630c0b9f36d5c1cc4d447d61fe51ff4bd60633f47ac"}, - {file = "mypy-1.18.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:030c52d0ea8144e721e49b1f68391e39553d7451f0c3f8a7565b59e19fcb608b"}, - {file = "mypy-1.18.2-cp39-cp39-win_amd64.whl", hash = "sha256:aa5e07ac1a60a253445797e42b8b2963c9675563a94f11291ab40718b016a7a0"}, - {file = "mypy-1.18.2-py3-none-any.whl", hash = "sha256:22a1748707dd62b58d2ae53562ffc4d7f8bcc727e8ac7cbc69c053ddc874d47e"}, - {file = "mypy-1.18.2.tar.gz", hash = "sha256:06a398102a5f203d7477b2923dda3634c36727fa5c237d8f859ef90c42a9924b"}, + {file = "mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec"}, + {file = "mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b"}, + {file = "mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6"}, + {file = "mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74"}, + {file = "mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1"}, + {file = "mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac"}, + {file = "mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288"}, + {file = "mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab"}, + {file = "mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6"}, + {file = "mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331"}, + {file = "mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925"}, + {file = "mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042"}, + {file = "mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1"}, + {file = "mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e"}, + {file = "mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2"}, + {file = "mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8"}, + {file = "mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a"}, + {file = "mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13"}, + {file = "mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250"}, + {file = "mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b"}, + {file = "mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e"}, + {file = "mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef"}, + {file = "mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75"}, + {file = "mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd"}, + {file = "mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1"}, + {file = "mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718"}, + {file = "mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b"}, + {file = "mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045"}, + {file = "mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957"}, + {file = "mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f"}, + {file = "mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3"}, + {file = "mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a"}, + {file = "mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67"}, + {file = "mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e"}, + {file = "mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376"}, + {file = "mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24"}, + {file = "mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247"}, + {file = "mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba"}, ] [package.dependencies] +librt = {version = ">=0.6.2", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" pathspec = ">=0.9.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} @@ -2436,6 +2608,7 @@ description = "A client library for executing notebooks. Formerly nbconvert's Ex optional = false python-versions = ">=3.9.0" groups = ["dev"] +markers = "python_version < \"3.11\"" files = [ {file = "nbclient-0.10.2-py3-none-any.whl", hash = "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d"}, {file = "nbclient-0.10.2.tar.gz", hash = "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193"}, @@ -2452,6 +2625,30 @@ dev = ["pre-commit"] docs = ["autodoc-traits", "flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "mock", "moto", "myst-parser", "nbconvert (>=7.1.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling", "testpath", "xmltodict"] test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.1.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] +[[package]] +name = "nbclient" +version = "0.10.4" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.10.0" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440"}, + {file = "nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9"}, +] + +[package.dependencies] +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +nbformat = ">=5.1.3" +traitlets = ">=5.4" + +[package.extras] +dev = ["pre-commit"] +docs = ["autodoc-traits", "flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "mock", "moto", "myst-parser", "nbconvert (>=7.1.0)", "pytest (>=9.0.1,<10)", "pytest-asyncio (>=1.3.0)", "pytest-cov (>=4.0)", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling", "testpath", "xmltodict"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.1.0)", "pytest (>=9.0.1,<10)", "pytest-asyncio (>=1.3.0)", "pytest-cov (>=4.0)", "testpath", "xmltodict"] + [[package]] name = "nbconvert" version = "7.16.6" @@ -2526,27 +2723,27 @@ files = [ [[package]] name = "notebook" -version = "7.4.7" +version = "7.5.1" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "notebook-7.4.7-py3-none-any.whl", hash = "sha256:362b7c95527f7dd3c4c84d410b782872fd9c734fb2524c11dd92758527b6eda6"}, - {file = "notebook-7.4.7.tar.gz", hash = "sha256:3f0a04027dfcee8a876de48fba13ab77ec8c12f72f848a222ed7f5081b9e342a"}, + {file = "notebook-7.5.1-py3-none-any.whl", hash = "sha256:f4e2451c19910c33b88709b84537e11f6368c1cdff1aa0c43db701aea535dd44"}, + {file = "notebook-7.5.1.tar.gz", hash = "sha256:b2fb4cef4d47d08c33aecce1c6c6e84be05436fbd791f88fce8df9fbca088b75"}, ] [package.dependencies] jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.4.9,<4.5" -jupyterlab-server = ">=2.27.1,<3" +jupyterlab = ">=4.5.1,<4.6" +jupyterlab-server = ">=2.28.0,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" [package.extras] dev = ["hatch", "pre-commit"] docs = ["myst-parser", "nbsphinx", "pydata-sphinx-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["importlib-resources (>=5.0) ; python_version < \"3.10\"", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.27.1,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] +test = ["importlib-resources (>=5.0) ; python_version < \"3.10\"", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.28.0,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] [[package]] name = "notebook-shim" @@ -2745,87 +2942,85 @@ files = [ [[package]] name = "numpy" -version = "2.3.4" +version = "2.4.0" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" groups = ["main", "examples"] markers = "python_version >= \"3.11\"" files = [ - {file = "numpy-2.3.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e78aecd2800b32e8347ce49316d3eaf04aed849cd5b38e0af39f829a4e59f5eb"}, - {file = "numpy-2.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fd09cc5d65bda1e79432859c40978010622112e9194e581e3415a3eccc7f43f"}, - {file = "numpy-2.3.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:1b219560ae2c1de48ead517d085bc2d05b9433f8e49d0955c82e8cd37bd7bf36"}, - {file = "numpy-2.3.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:bafa7d87d4c99752d07815ed7a2c0964f8ab311eb8168f41b910bd01d15b6032"}, - {file = "numpy-2.3.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36dc13af226aeab72b7abad501d370d606326a0029b9f435eacb3b8c94b8a8b7"}, - {file = "numpy-2.3.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7b2f9a18b5ff9824a6af80de4f37f4ec3c2aab05ef08f51c77a093f5b89adda"}, - {file = "numpy-2.3.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9984bd645a8db6ca15d850ff996856d8762c51a2239225288f08f9050ca240a0"}, - {file = "numpy-2.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:64c5825affc76942973a70acf438a8ab618dbd692b84cd5ec40a0a0509edc09a"}, - {file = "numpy-2.3.4-cp311-cp311-win32.whl", hash = "sha256:ed759bf7a70342f7817d88376eb7142fab9fef8320d6019ef87fae05a99874e1"}, - {file = "numpy-2.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:faba246fb30ea2a526c2e9645f61612341de1a83fb1e0c5edf4ddda5a9c10996"}, - {file = "numpy-2.3.4-cp311-cp311-win_arm64.whl", hash = "sha256:4c01835e718bcebe80394fd0ac66c07cbb90147ebbdad3dcecd3f25de2ae7e2c"}, - {file = "numpy-2.3.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ef1b5a3e808bc40827b5fa2c8196151a4c5abe110e1726949d7abddfe5c7ae11"}, - {file = "numpy-2.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c2f91f496a87235c6aaf6d3f3d89b17dba64996abadccb289f48456cff931ca9"}, - {file = "numpy-2.3.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f77e5b3d3da652b474cc80a14084927a5e86a5eccf54ca8ca5cbd697bf7f2667"}, - {file = "numpy-2.3.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:8ab1c5f5ee40d6e01cbe96de5863e39b215a4d24e7d007cad56c7184fdf4aeef"}, - {file = "numpy-2.3.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77b84453f3adcb994ddbd0d1c5d11db2d6bda1a2b7fd5ac5bd4649d6f5dc682e"}, - {file = "numpy-2.3.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4121c5beb58a7f9e6dfdee612cb24f4df5cd4db6e8261d7f4d7450a997a65d6a"}, - {file = "numpy-2.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:65611ecbb00ac9846efe04db15cbe6186f562f6bb7e5e05f077e53a599225d16"}, - {file = "numpy-2.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dabc42f9c6577bcc13001b8810d300fe814b4cfbe8a92c873f269484594f9786"}, - {file = "numpy-2.3.4-cp312-cp312-win32.whl", hash = "sha256:a49d797192a8d950ca59ee2d0337a4d804f713bb5c3c50e8db26d49666e351dc"}, - {file = "numpy-2.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:985f1e46358f06c2a09921e8921e2c98168ed4ae12ccd6e5e87a4f1857923f32"}, - {file = "numpy-2.3.4-cp312-cp312-win_arm64.whl", hash = "sha256:4635239814149e06e2cb9db3dd584b2fa64316c96f10656983b8026a82e6e4db"}, - {file = "numpy-2.3.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c090d4860032b857d94144d1a9976b8e36709e40386db289aaf6672de2a81966"}, - {file = "numpy-2.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a13fc473b6db0be619e45f11f9e81260f7302f8d180c49a22b6e6120022596b3"}, - {file = "numpy-2.3.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:3634093d0b428e6c32c3a69b78e554f0cd20ee420dcad5a9f3b2a63762ce4197"}, - {file = "numpy-2.3.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:043885b4f7e6e232d7df4f51ffdef8c36320ee9d5f227b380ea636722c7ed12e"}, - {file = "numpy-2.3.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4ee6a571d1e4f0ea6d5f22d6e5fbd6ed1dc2b18542848e1e7301bd190500c9d7"}, - {file = "numpy-2.3.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc8a63918b04b8571789688b2780ab2b4a33ab44bfe8ccea36d3eba51228c953"}, - {file = "numpy-2.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:40cc556d5abbc54aabe2b1ae287042d7bdb80c08edede19f0c0afb36ae586f37"}, - {file = "numpy-2.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ecb63014bb7f4ce653f8be7f1df8cbc6093a5a2811211770f6606cc92b5a78fd"}, - {file = "numpy-2.3.4-cp313-cp313-win32.whl", hash = "sha256:e8370eb6925bb8c1c4264fec52b0384b44f675f191df91cbe0140ec9f0955646"}, - {file = "numpy-2.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:56209416e81a7893036eea03abcb91c130643eb14233b2515c90dcac963fe99d"}, - {file = "numpy-2.3.4-cp313-cp313-win_arm64.whl", hash = "sha256:a700a4031bc0fd6936e78a752eefb79092cecad2599ea9c8039c548bc097f9bc"}, - {file = "numpy-2.3.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:86966db35c4040fdca64f0816a1c1dd8dbd027d90fca5a57e00e1ca4cd41b879"}, - {file = "numpy-2.3.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:838f045478638b26c375ee96ea89464d38428c69170360b23a1a50fa4baa3562"}, - {file = "numpy-2.3.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d7315ed1dab0286adca467377c8381cd748f3dc92235f22a7dfc42745644a96a"}, - {file = "numpy-2.3.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:84f01a4d18b2cc4ade1814a08e5f3c907b079c847051d720fad15ce37aa930b6"}, - {file = "numpy-2.3.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:817e719a868f0dacde4abdfc5c1910b301877970195db9ab6a5e2c4bd5b121f7"}, - {file = "numpy-2.3.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85e071da78d92a214212cacea81c6da557cab307f2c34b5f85b628e94803f9c0"}, - {file = "numpy-2.3.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2ec646892819370cf3558f518797f16597b4e4669894a2ba712caccc9da53f1f"}, - {file = "numpy-2.3.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:035796aaaddfe2f9664b9a9372f089cfc88bd795a67bd1bfe15e6e770934cf64"}, - {file = "numpy-2.3.4-cp313-cp313t-win32.whl", hash = "sha256:fea80f4f4cf83b54c3a051f2f727870ee51e22f0248d3114b8e755d160b38cfb"}, - {file = "numpy-2.3.4-cp313-cp313t-win_amd64.whl", hash = "sha256:15eea9f306b98e0be91eb344a94c0e630689ef302e10c2ce5f7e11905c704f9c"}, - {file = "numpy-2.3.4-cp313-cp313t-win_arm64.whl", hash = "sha256:b6c231c9c2fadbae4011ca5e7e83e12dc4a5072f1a1d85a0a7b3ed754d145a40"}, - {file = "numpy-2.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:81c3e6d8c97295a7360d367f9f8553973651b76907988bb6066376bc2252f24e"}, - {file = "numpy-2.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7c26b0b2bf58009ed1f38a641f3db4be8d960a417ca96d14e5b06df1506d41ff"}, - {file = "numpy-2.3.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:62b2198c438058a20b6704351b35a1d7db881812d8512d67a69c9de1f18ca05f"}, - {file = "numpy-2.3.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:9d729d60f8d53a7361707f4b68a9663c968882dd4f09e0d58c044c8bf5faee7b"}, - {file = "numpy-2.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd0c630cf256b0a7fd9d0a11c9413b42fef5101219ce6ed5a09624f5a65392c7"}, - {file = "numpy-2.3.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5e081bc082825f8b139f9e9fe42942cb4054524598aaeb177ff476cc76d09d2"}, - {file = "numpy-2.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:15fb27364ed84114438fff8aaf998c9e19adbeba08c0b75409f8c452a8692c52"}, - {file = "numpy-2.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:85d9fb2d8cd998c84d13a79a09cc0c1091648e848e4e6249b0ccd7f6b487fa26"}, - {file = "numpy-2.3.4-cp314-cp314-win32.whl", hash = "sha256:e73d63fd04e3a9d6bc187f5455d81abfad05660b212c8804bf3b407e984cd2bc"}, - {file = "numpy-2.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:3da3491cee49cf16157e70f607c03a217ea6647b1cea4819c4f48e53d49139b9"}, - {file = "numpy-2.3.4-cp314-cp314-win_arm64.whl", hash = "sha256:6d9cd732068e8288dbe2717177320723ccec4fb064123f0caf9bbd90ab5be868"}, - {file = "numpy-2.3.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:22758999b256b595cf0b1d102b133bb61866ba5ceecf15f759623b64c020c9ec"}, - {file = "numpy-2.3.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9cb177bc55b010b19798dc5497d540dea67fd13a8d9e882b2dae71de0cf09eb3"}, - {file = "numpy-2.3.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0f2bcc76f1e05e5ab58893407c63d90b2029908fa41f9f1cc51eecce936c3365"}, - {file = "numpy-2.3.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:8dc20bde86802df2ed8397a08d793da0ad7a5fd4ea3ac85d757bf5dd4ad7c252"}, - {file = "numpy-2.3.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e199c087e2aa71c8f9ce1cb7a8e10677dc12457e7cc1be4798632da37c3e86e"}, - {file = "numpy-2.3.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85597b2d25ddf655495e2363fe044b0ae999b75bc4d630dc0d886484b03a5eb0"}, - {file = "numpy-2.3.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:04a69abe45b49c5955923cf2c407843d1c85013b424ae8a560bba16c92fe44a0"}, - {file = "numpy-2.3.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e1708fac43ef8b419c975926ce1eaf793b0c13b7356cfab6ab0dc34c0a02ac0f"}, - {file = "numpy-2.3.4-cp314-cp314t-win32.whl", hash = "sha256:863e3b5f4d9915aaf1b8ec79ae560ad21f0b8d5e3adc31e73126491bb86dee1d"}, - {file = "numpy-2.3.4-cp314-cp314t-win_amd64.whl", hash = "sha256:962064de37b9aef801d33bc579690f8bfe6c5e70e29b61783f60bcba838a14d6"}, - {file = "numpy-2.3.4-cp314-cp314t-win_arm64.whl", hash = "sha256:8b5a9a39c45d852b62693d9b3f3e0fe052541f804296ff401a72a1b60edafb29"}, - {file = "numpy-2.3.4-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6e274603039f924c0fe5cb73438fa9246699c78a6df1bd3decef9ae592ae1c05"}, - {file = "numpy-2.3.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d149aee5c72176d9ddbc6803aef9c0f6d2ceeea7626574fc68518da5476fa346"}, - {file = "numpy-2.3.4-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:6d34ed9db9e6395bb6cd33286035f73a59b058169733a9db9f85e650b88df37e"}, - {file = "numpy-2.3.4-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:fdebe771ca06bb8d6abce84e51dca9f7921fe6ad34a0c914541b063e9a68928b"}, - {file = "numpy-2.3.4-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e92defe6c08211eb77902253b14fe5b480ebc5112bc741fd5e9cd0608f847"}, - {file = "numpy-2.3.4-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13b9062e4f5c7ee5c7e5be96f29ba71bc5a37fed3d1d77c37390ae00724d296d"}, - {file = "numpy-2.3.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:81b3a59793523e552c4a96109dde028aa4448ae06ccac5a76ff6532a85558a7f"}, - {file = "numpy-2.3.4.tar.gz", hash = "sha256:a7d018bfedb375a8d979ac758b120ba846a7fe764911a64465fd87b8729f4a6a"}, + {file = "numpy-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:316b2f2584682318539f0bcaca5a496ce9ca78c88066579ebd11fd06f8e4741e"}, + {file = "numpy-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2718c1de8504121714234b6f8241d0019450353276c88b9453c9c3d92e101db"}, + {file = "numpy-2.4.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:21555da4ec4a0c942520ead42c3b0dc9477441e085c42b0fbdd6a084869a6f6b"}, + {file = "numpy-2.4.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:413aa561266a4be2d06cd2b9665e89d9f54c543f418773076a76adcf2af08bc7"}, + {file = "numpy-2.4.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0feafc9e03128074689183031181fac0897ff169692d8492066e949041096548"}, + {file = "numpy-2.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8fdfed3deaf1928fb7667d96e0567cdf58c2b370ea2ee7e586aa383ec2cb346"}, + {file = "numpy-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e06a922a469cae9a57100864caf4f8a97a1026513793969f8ba5b63137a35d25"}, + {file = "numpy-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:927ccf5cd17c48f801f4ed43a7e5673a2724bd2171460be3e3894e6e332ef83a"}, + {file = "numpy-2.4.0-cp311-cp311-win32.whl", hash = "sha256:882567b7ae57c1b1a0250208cc21a7976d8cbcc49d5a322e607e6f09c9e0bd53"}, + {file = "numpy-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:8b986403023c8f3bf8f487c2e6186afda156174d31c175f747d8934dfddf3479"}, + {file = "numpy-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:3f3096405acc48887458bbf9f6814d43785ac7ba2a57ea6442b581dedbc60ce6"}, + {file = "numpy-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2a8b6bb8369abefb8bd1801b054ad50e02b3275c8614dc6e5b0373c305291037"}, + {file = "numpy-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e284ca13d5a8367e43734148622caf0b261b275673823593e3e3634a6490f83"}, + {file = "numpy-2.4.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:49ff32b09f5aa0cd30a20c2b39db3e669c845589f2b7fc910365210887e39344"}, + {file = "numpy-2.4.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:36cbfb13c152b1c7c184ddac43765db8ad672567e7bafff2cc755a09917ed2e6"}, + {file = "numpy-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35ddc8f4914466e6fc954c76527aa91aa763682a4f6d73249ef20b418fe6effb"}, + {file = "numpy-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc578891de1db95b2a35001b695451767b580bb45753717498213c5ff3c41d63"}, + {file = "numpy-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98e81648e0b36e325ab67e46b5400a7a6d4a22b8a7c8e8bbfe20e7db7906bf95"}, + {file = "numpy-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d57b5046c120561ba8fa8e4030fbb8b822f3063910fa901ffadf16e2b7128ad6"}, + {file = "numpy-2.4.0-cp312-cp312-win32.whl", hash = "sha256:92190db305a6f48734d3982f2c60fa30d6b5ee9bff10f2887b930d7b40119f4c"}, + {file = "numpy-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:680060061adb2d74ce352628cb798cfdec399068aa7f07ba9fb818b2b3305f98"}, + {file = "numpy-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:39699233bc72dd482da1415dcb06076e32f60eddc796a796c5fb6c5efce94667"}, + {file = "numpy-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a152d86a3ae00ba5f47b3acf3b827509fd0b6cb7d3259665e63dafbad22a75ea"}, + {file = "numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d"}, + {file = "numpy-2.4.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:009bd0ea12d3c784b6639a8457537016ce5172109e585338e11334f6a7bb88ee"}, + {file = "numpy-2.4.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5fe44e277225fd3dff6882d86d3d447205d43532c3627313d17e754fb3905a0e"}, + {file = "numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2"}, + {file = "numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a"}, + {file = "numpy-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba0cb30acd3ef11c94dc27fbfba68940652492bc107075e7ffe23057f9425681"}, + {file = "numpy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60e8c196cd82cbbd4f130b5290007e13e6de3eca79f0d4d38014769d96a7c475"}, + {file = "numpy-2.4.0-cp313-cp313-win32.whl", hash = "sha256:5f48cb3e88fbc294dc90e215d86fbaf1c852c63dbdb6c3a3e63f45c4b57f7344"}, + {file = "numpy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:a899699294f28f7be8992853c0c60741f16ff199205e2e6cdca155762cbaa59d"}, + {file = "numpy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9198f447e1dc5647d07c9a6bbe2063cc0132728cc7175b39dbc796da5b54920d"}, + {file = "numpy-2.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74623f2ab5cc3f7c886add4f735d1031a1d2be4a4ae63c0546cfd74e7a31ddf6"}, + {file = "numpy-2.4.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0804a8e4ab070d1d35496e65ffd3cf8114c136a2b81f61dfab0de4b218aacfd5"}, + {file = "numpy-2.4.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:02a2038eb27f9443a8b266a66911e926566b5a6ffd1a689b588f7f35b81e7dc3"}, + {file = "numpy-2.4.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1889b3a3f47a7b5bee16bc25a2145bd7cb91897f815ce3499db64c7458b6d91d"}, + {file = "numpy-2.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85eef4cb5625c47ee6425c58a3502555e10f45ee973da878ac8248ad58c136f3"}, + {file = "numpy-2.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6dc8b7e2f4eb184b37655195f421836cfae6f58197b67e3ffc501f1333d993fa"}, + {file = "numpy-2.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:44aba2f0cafd287871a495fb3163408b0bd25bbce135c6f621534a07f4f7875c"}, + {file = "numpy-2.4.0-cp313-cp313t-win32.whl", hash = "sha256:20c115517513831860c573996e395707aa9fb691eb179200125c250e895fcd93"}, + {file = "numpy-2.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b48e35f4ab6f6a7597c46e301126ceba4c44cd3280e3750f85db48b082624fa4"}, + {file = "numpy-2.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:4d1cfce39e511069b11e67cd0bd78ceff31443b7c9e5c04db73c7a19f572967c"}, + {file = "numpy-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c95eb6db2884917d86cde0b4d4cf31adf485c8ec36bf8696dd66fa70de96f36b"}, + {file = "numpy-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:65167da969cd1ec3a1df31cb221ca3a19a8aaa25370ecb17d428415e93c1935e"}, + {file = "numpy-2.4.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3de19cfecd1465d0dcf8a5b5ea8b3155b42ed0b639dba4b71e323d74f2a3be5e"}, + {file = "numpy-2.4.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6c05483c3136ac4c91b4e81903cb53a8707d316f488124d0398499a4f8e8ef51"}, + {file = "numpy-2.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36667db4d6c1cea79c8930ab72fadfb4060feb4bfe724141cd4bd064d2e5f8ce"}, + {file = "numpy-2.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9a818668b674047fd88c4cddada7ab8f1c298812783e8328e956b78dc4807f9f"}, + {file = "numpy-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ee32359fb7543b7b7bd0b2f46294db27e29e7bbdf70541e81b190836cd83ded"}, + {file = "numpy-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e493962256a38f58283de033d8af176c5c91c084ea30f15834f7545451c42059"}, + {file = "numpy-2.4.0-cp314-cp314-win32.whl", hash = "sha256:6bbaebf0d11567fa8926215ae731e1d58e6ec28a8a25235b8a47405d301332db"}, + {file = "numpy-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:3d857f55e7fdf7c38ab96c4558c95b97d1c685be6b05c249f5fdafcbd6f9899e"}, + {file = "numpy-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:bb50ce5fb202a26fd5404620e7ef820ad1ab3558b444cb0b55beb7ef66cd2d63"}, + {file = "numpy-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:355354388cba60f2132df297e2d53053d4063f79077b67b481d21276d61fc4df"}, + {file = "numpy-2.4.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:1d8f9fde5f6dc1b6fc34df8162f3b3079365468703fee7f31d4e0cc8c63baed9"}, + {file = "numpy-2.4.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e0434aa22c821f44eeb4c650b81c7fbdd8c0122c6c4b5a576a76d5a35625ecd9"}, + {file = "numpy-2.4.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40483b2f2d3ba7aad426443767ff5632ec3156ef09742b96913787d13c336471"}, + {file = "numpy-2.4.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6a7664ddd9746e20b7325351fe1a8408d0a2bf9c63b5e898290ddc8f09544"}, + {file = "numpy-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ecb0019d44f4cdb50b676c5d0cb4b1eae8e15d1ed3d3e6639f986fc92b2ec52c"}, + {file = "numpy-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d0ffd9e2e4441c96a9c91ec1783285d80bf835b677853fc2770a89d50c1e48ac"}, + {file = "numpy-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:77f0d13fa87036d7553bf81f0e1fe3ce68d14c9976c9851744e4d3e91127e95f"}, + {file = "numpy-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b1f5b45829ac1848893f0ddf5cb326110604d6df96cdc255b0bf9edd154104d4"}, + {file = "numpy-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:23a3e9d1a6f360267e8fbb38ba5db355a6a7e9be71d7fce7ab3125e88bb646c8"}, + {file = "numpy-2.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b54c83f1c0c0f1d748dca0af516062b8829d53d1f0c402be24b4257a9c48ada6"}, + {file = "numpy-2.4.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:aabb081ca0ec5d39591fc33018cd4b3f96e1a2dd6756282029986d00a785fba4"}, + {file = "numpy-2.4.0-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:8eafe7c36c8430b7794edeab3087dec7bf31d634d92f2af9949434b9d1964cba"}, + {file = "numpy-2.4.0-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2f585f52b2baf07ff3356158d9268ea095e221371f1074fadea2f42544d58b4d"}, + {file = "numpy-2.4.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32ed06d0fe9cae27d8fb5f400c63ccee72370599c75e683a6358dd3a4fb50aaf"}, + {file = "numpy-2.4.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:57c540ed8fb1f05cb997c6761cd56db72395b0d6985e90571ff660452ade4f98"}, + {file = "numpy-2.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a39fb973a726e63223287adc6dafe444ce75af952d711e400f3bf2b36ef55a7b"}, + {file = "numpy-2.4.0.tar.gz", hash = "sha256:6e504f7b16118198f138ef31ba24d985b124c2c469fe8467007cf30fd992f934"}, ] [[package]] @@ -3027,218 +3222,232 @@ files = [ [package.dependencies] ptyprocess = ">=0.5" -[[package]] -name = "pickleshare" -version = "0.7.5" -description = "Tiny 'shelve'-like database with concurrency support" -optional = false -python-versions = "*" -groups = ["dev"] -markers = "python_version < \"3.11\"" -files = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, -] - [[package]] name = "pillow" -version = "10.4.0" +version = "11.3.0" description = "Python Imaging Library (Fork)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main", "examples"] markers = "python_version < \"3.11\"" files = [ - {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, - {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, - {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, - {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, - {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, - {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, - {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, - {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, - {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, - {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, - {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, - {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, - {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, - {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, - {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, - {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, - {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, - {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, - {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, - {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, - {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, - {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, - {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, - {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, - {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, - {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, - {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, - {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, - {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, - {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, - {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, - {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, - {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, - {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, - {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, - {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, - {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, - {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, - {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, + {file = "pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860"}, + {file = "pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e"}, + {file = "pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6"}, + {file = "pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f"}, + {file = "pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94"}, + {file = "pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0"}, + {file = "pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac"}, + {file = "pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d"}, + {file = "pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149"}, + {file = "pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d"}, + {file = "pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b"}, + {file = "pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3"}, + {file = "pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51"}, + {file = "pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c"}, + {file = "pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788"}, + {file = "pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31"}, + {file = "pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a"}, + {file = "pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214"}, + {file = "pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635"}, + {file = "pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b"}, + {file = "pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12"}, + {file = "pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db"}, + {file = "pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d"}, + {file = "pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71"}, + {file = "pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada"}, + {file = "pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8"}, + {file = "pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523"}, ] [package.extras] -docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] fpx = ["olefile"] mic = ["olefile"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +test-arrow = ["pyarrow"] +tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] typing = ["typing-extensions ; python_version < \"3.10\""] xmp = ["defusedxml"] [[package]] name = "pillow" -version = "12.0.0" +version = "12.1.0" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" groups = ["main", "examples"] markers = "python_version >= \"3.11\"" files = [ - {file = "pillow-12.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:3adfb466bbc544b926d50fe8f4a4e6abd8c6bffd28a26177594e6e9b2b76572b"}, - {file = "pillow-12.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1ac11e8ea4f611c3c0147424eae514028b5e9077dd99ab91e1bd7bc33ff145e1"}, - {file = "pillow-12.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d49e2314c373f4c2b39446fb1a45ed333c850e09d0c59ac79b72eb3b95397363"}, - {file = "pillow-12.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c7b2a63fd6d5246349f3d3f37b14430d73ee7e8173154461785e43036ffa96ca"}, - {file = "pillow-12.0.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d64317d2587c70324b79861babb9c09f71fbb780bad212018874b2c013d8600e"}, - {file = "pillow-12.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d77153e14b709fd8b8af6f66a3afbb9ed6e9fc5ccf0b6b7e1ced7b036a228782"}, - {file = "pillow-12.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:32ed80ea8a90ee3e6fa08c21e2e091bba6eda8eccc83dbc34c95169507a91f10"}, - {file = "pillow-12.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c828a1ae702fc712978bda0320ba1b9893d99be0badf2647f693cc01cf0f04fa"}, - {file = "pillow-12.0.0-cp310-cp310-win32.whl", hash = "sha256:bd87e140e45399c818fac4247880b9ce719e4783d767e030a883a970be632275"}, - {file = "pillow-12.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:455247ac8a4cfb7b9bc45b7e432d10421aea9fc2e74d285ba4072688a74c2e9d"}, - {file = "pillow-12.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:6ace95230bfb7cd79ef66caa064bbe2f2a1e63d93471c3a2e1f1348d9f22d6b7"}, - {file = "pillow-12.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0fd00cac9c03256c8b2ff58f162ebcd2587ad3e1f2e397eab718c47e24d231cc"}, - {file = "pillow-12.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3475b96f5908b3b16c47533daaa87380c491357d197564e0ba34ae75c0f3257"}, - {file = "pillow-12.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:110486b79f2d112cf6add83b28b627e369219388f64ef2f960fef9ebaf54c642"}, - {file = "pillow-12.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5269cc1caeedb67e6f7269a42014f381f45e2e7cd42d834ede3c703a1d915fe3"}, - {file = "pillow-12.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa5129de4e174daccbc59d0a3b6d20eaf24417d59851c07ebb37aeb02947987c"}, - {file = "pillow-12.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bee2a6db3a7242ea309aa7ee8e2780726fed67ff4e5b40169f2c940e7eb09227"}, - {file = "pillow-12.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:90387104ee8400a7b4598253b4c406f8958f59fcf983a6cea2b50d59f7d63d0b"}, - {file = "pillow-12.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc91a56697869546d1b8f0a3ff35224557ae7f881050e99f615e0119bf934b4e"}, - {file = "pillow-12.0.0-cp311-cp311-win32.whl", hash = "sha256:27f95b12453d165099c84f8a8bfdfd46b9e4bda9e0e4b65f0635430027f55739"}, - {file = "pillow-12.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:b583dc9070312190192631373c6c8ed277254aa6e6084b74bdd0a6d3b221608e"}, - {file = "pillow-12.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:759de84a33be3b178a64c8ba28ad5c135900359e85fb662bc6e403ad4407791d"}, - {file = "pillow-12.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371"}, - {file = "pillow-12.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082"}, - {file = "pillow-12.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f"}, - {file = "pillow-12.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d"}, - {file = "pillow-12.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953"}, - {file = "pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8"}, - {file = "pillow-12.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79"}, - {file = "pillow-12.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba"}, - {file = "pillow-12.0.0-cp312-cp312-win32.whl", hash = "sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0"}, - {file = "pillow-12.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a"}, - {file = "pillow-12.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad"}, - {file = "pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643"}, - {file = "pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4"}, - {file = "pillow-12.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399"}, - {file = "pillow-12.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5"}, - {file = "pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b"}, - {file = "pillow-12.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3"}, - {file = "pillow-12.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07"}, - {file = "pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e"}, - {file = "pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344"}, - {file = "pillow-12.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27"}, - {file = "pillow-12.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79"}, - {file = "pillow-12.0.0-cp313-cp313-win32.whl", hash = "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098"}, - {file = "pillow-12.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905"}, - {file = "pillow-12.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a"}, - {file = "pillow-12.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3"}, - {file = "pillow-12.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced"}, - {file = "pillow-12.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b"}, - {file = "pillow-12.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d"}, - {file = "pillow-12.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a"}, - {file = "pillow-12.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe"}, - {file = "pillow-12.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee"}, - {file = "pillow-12.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef"}, - {file = "pillow-12.0.0-cp313-cp313t-win32.whl", hash = "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9"}, - {file = "pillow-12.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b"}, - {file = "pillow-12.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47"}, - {file = "pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9"}, - {file = "pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2"}, - {file = "pillow-12.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a"}, - {file = "pillow-12.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b"}, - {file = "pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad"}, - {file = "pillow-12.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01"}, - {file = "pillow-12.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c"}, - {file = "pillow-12.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e"}, - {file = "pillow-12.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e"}, - {file = "pillow-12.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9"}, - {file = "pillow-12.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab"}, - {file = "pillow-12.0.0-cp314-cp314-win32.whl", hash = "sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b"}, - {file = "pillow-12.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b"}, - {file = "pillow-12.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0"}, - {file = "pillow-12.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6"}, - {file = "pillow-12.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6"}, - {file = "pillow-12.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1"}, - {file = "pillow-12.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e"}, - {file = "pillow-12.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca"}, - {file = "pillow-12.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925"}, - {file = "pillow-12.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8"}, - {file = "pillow-12.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4"}, - {file = "pillow-12.0.0-cp314-cp314t-win32.whl", hash = "sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52"}, - {file = "pillow-12.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a"}, - {file = "pillow-12.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7"}, - {file = "pillow-12.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b22bd8c974942477156be55a768f7aa37c46904c175be4e158b6a86e3a6b7ca8"}, - {file = "pillow-12.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:805ebf596939e48dbb2e4922a1d3852cfc25c38160751ce02da93058b48d252a"}, - {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cae81479f77420d217def5f54b5b9d279804d17e982e0f2fa19b1d1e14ab5197"}, - {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeaefa96c768fc66818730b952a862235d68825c178f1b3ffd4efd7ad2edcb7c"}, - {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09f2d0abef9e4e2f349305a4f8cc784a8a6c2f58a8c4892eea13b10a943bd26e"}, - {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bdee52571a343d721fb2eb3b090a82d959ff37fc631e3f70422e0c2e029f3e76"}, - {file = "pillow-12.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b290fd8aa38422444d4b50d579de197557f182ef1068b75f5aa8558638b8d0a5"}, - {file = "pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353"}, + {file = "pillow-12.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:fb125d860738a09d363a88daa0f59c4533529a90e564785e20fe875b200b6dbd"}, + {file = "pillow-12.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cad302dc10fac357d3467a74a9561c90609768a6f73a1923b0fd851b6486f8b0"}, + {file = "pillow-12.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a40905599d8079e09f25027423aed94f2823adaf2868940de991e53a449e14a8"}, + {file = "pillow-12.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:92a7fe4225365c5e3a8e598982269c6d6698d3e783b3b1ae979e7819f9cd55c1"}, + {file = "pillow-12.1.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f10c98f49227ed8383d28174ee95155a675c4ed7f85e2e573b04414f7e371bda"}, + {file = "pillow-12.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8637e29d13f478bc4f153d8daa9ffb16455f0a6cb287da1b432fdad2bfbd66c7"}, + {file = "pillow-12.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:21e686a21078b0f9cb8c8a961d99e6a4ddb88e0fc5ea6e130172ddddc2e5221a"}, + {file = "pillow-12.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2415373395a831f53933c23ce051021e79c8cd7979822d8cc478547a3f4da8ef"}, + {file = "pillow-12.1.0-cp310-cp310-win32.whl", hash = "sha256:e75d3dba8fc1ddfec0cd752108f93b83b4f8d6ab40e524a95d35f016b9683b09"}, + {file = "pillow-12.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:64efdf00c09e31efd754448a383ea241f55a994fd079866b92d2bbff598aad91"}, + {file = "pillow-12.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f188028b5af6b8fb2e9a76ac0f841a575bd1bd396e46ef0840d9b88a48fdbcea"}, + {file = "pillow-12.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:a83e0850cb8f5ac975291ebfc4170ba481f41a28065277f7f735c202cd8e0af3"}, + {file = "pillow-12.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b6e53e82ec2db0717eabb276aa56cf4e500c9a7cec2c2e189b55c24f65a3e8c0"}, + {file = "pillow-12.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:40a8e3b9e8773876d6e30daed22f016509e3987bab61b3b7fe309d7019a87451"}, + {file = "pillow-12.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:800429ac32c9b72909c671aaf17ecd13110f823ddb7db4dfef412a5587c2c24e"}, + {file = "pillow-12.1.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b022eaaf709541b391ee069f0022ee5b36c709df71986e3f7be312e46f42c84"}, + {file = "pillow-12.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f345e7bc9d7f368887c712aa5054558bad44d2a301ddf9248599f4161abc7c0"}, + {file = "pillow-12.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d70347c8a5b7ccd803ec0c85c8709f036e6348f1e6a5bf048ecd9c64d3550b8b"}, + {file = "pillow-12.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fcc52d86ce7a34fd17cb04e87cfdb164648a3662a6f20565910a99653d66c18"}, + {file = "pillow-12.1.0-cp311-cp311-win32.whl", hash = "sha256:3ffaa2f0659e2f740473bcf03c702c39a8d4b2b7ffc629052028764324842c64"}, + {file = "pillow-12.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:806f3987ffe10e867bab0ddad45df1148a2b98221798457fa097ad85d6e8bc75"}, + {file = "pillow-12.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9f5fefaca968e700ad1a4a9de98bf0869a94e397fe3524c4c9450c1445252304"}, + {file = "pillow-12.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a332ac4ccb84b6dde65dbace8431f3af08874bf9770719d32a635c4ef411b18b"}, + {file = "pillow-12.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:907bfa8a9cb790748a9aa4513e37c88c59660da3bcfffbd24a7d9e6abf224551"}, + {file = "pillow-12.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:efdc140e7b63b8f739d09a99033aa430accce485ff78e6d311973a67b6bf3208"}, + {file = "pillow-12.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bef9768cab184e7ae6e559c032e95ba8d07b3023c289f79a2bd36e8bf85605a5"}, + {file = "pillow-12.1.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:742aea052cf5ab5034a53c3846165bc3ce88d7c38e954120db0ab867ca242661"}, + {file = "pillow-12.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a6dfc2af5b082b635af6e08e0d1f9f1c4e04d17d4e2ca0ef96131e85eda6eb17"}, + {file = "pillow-12.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:609e89d9f90b581c8d16358c9087df76024cf058fa693dd3e1e1620823f39670"}, + {file = "pillow-12.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:43b4899cfd091a9693a1278c4982f3e50f7fb7cff5153b05174b4afc9593b616"}, + {file = "pillow-12.1.0-cp312-cp312-win32.whl", hash = "sha256:aa0c9cc0b82b14766a99fbe6084409972266e82f459821cd26997a488a7261a7"}, + {file = "pillow-12.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:d70534cea9e7966169ad29a903b99fc507e932069a881d0965a1a84bb57f6c6d"}, + {file = "pillow-12.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:65b80c1ee7e14a87d6a068dd3b0aea268ffcabfe0498d38661b00c5b4b22e74c"}, + {file = "pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1"}, + {file = "pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179"}, + {file = "pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0"}, + {file = "pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587"}, + {file = "pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac"}, + {file = "pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b"}, + {file = "pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea"}, + {file = "pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c"}, + {file = "pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc"}, + {file = "pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644"}, + {file = "pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c"}, + {file = "pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171"}, + {file = "pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a"}, + {file = "pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45"}, + {file = "pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d"}, + {file = "pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0"}, + {file = "pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554"}, + {file = "pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e"}, + {file = "pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82"}, + {file = "pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4"}, + {file = "pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0"}, + {file = "pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b"}, + {file = "pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65"}, + {file = "pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0"}, + {file = "pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8"}, + {file = "pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91"}, + {file = "pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796"}, + {file = "pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd"}, + {file = "pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13"}, + {file = "pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e"}, + {file = "pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643"}, + {file = "pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5"}, + {file = "pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de"}, + {file = "pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9"}, + {file = "pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a"}, + {file = "pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a"}, + {file = "pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030"}, + {file = "pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94"}, + {file = "pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4"}, + {file = "pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2"}, + {file = "pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61"}, + {file = "pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51"}, + {file = "pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc"}, + {file = "pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14"}, + {file = "pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8"}, + {file = "pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924"}, + {file = "pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef"}, + {file = "pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988"}, + {file = "pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6"}, + {file = "pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831"}, + {file = "pillow-12.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ca94b6aac0d7af2a10ba08c0f888b3d5114439b6b3ef39968378723622fed377"}, + {file = "pillow-12.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:351889afef0f485b84078ea40fe33727a0492b9af3904661b0abbafee0355b72"}, + {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb0984b30e973f7e2884362b7d23d0a348c7143ee559f38ef3eaab640144204c"}, + {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84cabc7095dd535ca934d57e9ce2a72ffd216e435a84acb06b2277b1de2689bd"}, + {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53d8b764726d3af1a138dd353116f774e3862ec7e3794e0c8781e30db0f35dfc"}, + {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5da841d81b1a05ef940a8567da92decaa15bc4d7dedb540a8c219ad83d91808a"}, + {file = "pillow-12.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:75af0b4c229ac519b155028fa1be632d812a519abba9b46b20e50c6caa184f19"}, + {file = "pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9"}, ] [package.extras] @@ -3251,33 +3460,33 @@ xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.3.6" +version = "4.4.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] markers = "python_version < \"3.11\"" files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, + {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, + {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] [[package]] name = "platformdirs" -version = "4.5.0" +version = "4.5.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["dev"] markers = "python_version >= \"3.11\"" files = [ - {file = "platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3"}, - {file = "platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312"}, + {file = "platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31"}, + {file = "platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda"}, ] [package.extras] @@ -3397,36 +3606,38 @@ wcwidth = "*" [[package]] name = "psutil" -version = "7.1.2" +version = "7.2.1" description = "Cross-platform lib for process and system monitoring." optional = false python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "psutil-7.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0cc5c6889b9871f231ed5455a9a02149e388fffcb30b607fb7a8896a6d95f22e"}, - {file = "psutil-7.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8e9e77a977208d84aa363a4a12e0f72189d58bbf4e46b49aae29a2c6e93ef206"}, - {file = "psutil-7.1.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d9623a5e4164d2220ecceb071f4b333b3c78866141e8887c072129185f41278"}, - {file = "psutil-7.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:364b1c10fe4ed59c89ec49e5f1a70da353b27986fa8233b4b999df4742a5ee2f"}, - {file = "psutil-7.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f101ef84de7e05d41310e3ccbdd65a6dd1d9eed85e8aaf0758405d022308e204"}, - {file = "psutil-7.1.2-cp313-cp313t-win_arm64.whl", hash = "sha256:20c00824048a95de67f00afedc7b08b282aa08638585b0206a9fb51f28f1a165"}, - {file = "psutil-7.1.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e09cfe92aa8e22b1ec5e2d394820cf86c5dff6367ac3242366485dfa874d43bc"}, - {file = "psutil-7.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fa6342cf859c48b19df3e4aa170e4cfb64aadc50b11e06bb569c6c777b089c9e"}, - {file = "psutil-7.1.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:625977443498ee7d6c1e63e93bacca893fd759a66c5f635d05e05811d23fb5ee"}, - {file = "psutil-7.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a24bcd7b7f2918d934af0fb91859f621b873d6aa81267575e3655cd387572a7"}, - {file = "psutil-7.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:329f05610da6380982e6078b9d0881d9ab1e9a7eb7c02d833bfb7340aa634e31"}, - {file = "psutil-7.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7b04c29e3c0c888e83ed4762b70f31e65c42673ea956cefa8ced0e31e185f582"}, - {file = "psutil-7.1.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c9ba5c19f2d46203ee8c152c7b01df6eec87d883cfd8ee1af2ef2727f6b0f814"}, - {file = "psutil-7.1.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:2a486030d2fe81bec023f703d3d155f4823a10a47c36784c84f1cc7f8d39bedb"}, - {file = "psutil-7.1.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3efd8fc791492e7808a51cb2b94889db7578bfaea22df931424f874468e389e3"}, - {file = "psutil-7.1.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2aeb9b64f481b8eabfc633bd39e0016d4d8bbcd590d984af764d80bf0851b8a"}, - {file = "psutil-7.1.2-cp37-abi3-win_amd64.whl", hash = "sha256:8e17852114c4e7996fe9da4745c2bdef001ebbf2f260dec406290e66628bdb91"}, - {file = "psutil-7.1.2-cp37-abi3-win_arm64.whl", hash = "sha256:3e988455e61c240cc879cb62a008c2699231bf3e3d061d7fce4234463fd2abb4"}, - {file = "psutil-7.1.2.tar.gz", hash = "sha256:aa225cdde1335ff9684708ee8c72650f6598d5ed2114b9a7c5802030b1785018"}, + {file = "psutil-7.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9f33bb525b14c3ea563b2fd521a84d2fa214ec59e3e6a2858f78d0844dd60d"}, + {file = "psutil-7.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81442dac7abfc2f4f4385ea9e12ddf5a796721c0f6133260687fec5c3780fa49"}, + {file = "psutil-7.2.1-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea46c0d060491051d39f0d2cff4f98d5c72b288289f57a21556cc7d504db37fc"}, + {file = "psutil-7.2.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35630d5af80d5d0d49cfc4d64c1c13838baf6717a13effb35869a5919b854cdf"}, + {file = "psutil-7.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:923f8653416604e356073e6e0bccbe7c09990acef442def2f5640dd0faa9689f"}, + {file = "psutil-7.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cfbe6b40ca48019a51827f20d830887b3107a74a79b01ceb8cc8de4ccb17b672"}, + {file = "psutil-7.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:494c513ccc53225ae23eec7fe6e1482f1b8a44674241b54561f755a898650679"}, + {file = "psutil-7.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fce5f92c22b00cdefd1645aa58ab4877a01679e901555067b1bd77039aa589f"}, + {file = "psutil-7.2.1-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93f3f7b0bb07711b49626e7940d6fe52aa9940ad86e8f7e74842e73189712129"}, + {file = "psutil-7.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d34d2ca888208eea2b5c68186841336a7f5e0b990edec929be909353a202768a"}, + {file = "psutil-7.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2ceae842a78d1603753561132d5ad1b2f8a7979cb0c283f5b52fb4e6e14b1a79"}, + {file = "psutil-7.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:08a2f175e48a898c8eb8eace45ce01777f4785bc744c90aa2cc7f2fa5462a266"}, + {file = "psutil-7.2.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2e953fcfaedcfbc952b44744f22d16575d3aa78eb4f51ae74165b4e96e55f42"}, + {file = "psutil-7.2.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:05cc68dbb8c174828624062e73078e7e35406f4ca2d0866c272c2410d8ef06d1"}, + {file = "psutil-7.2.1-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e38404ca2bb30ed7267a46c02f06ff842e92da3bb8c5bfdadbd35a5722314d8"}, + {file = "psutil-7.2.1-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab2b98c9fc19f13f59628d94df5cc4cc4844bc572467d113a8b517d634e362c6"}, + {file = "psutil-7.2.1-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f78baafb38436d5a128f837fab2d92c276dfb48af01a240b861ae02b2413ada8"}, + {file = "psutil-7.2.1-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99a4cd17a5fdd1f3d014396502daa70b5ec21bf4ffe38393e152f8e449757d67"}, + {file = "psutil-7.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:b1b0671619343aa71c20ff9767eced0483e4fc9e1f489d50923738caf6a03c17"}, + {file = "psutil-7.2.1-cp37-abi3-win_arm64.whl", hash = "sha256:0d67c1822c355aa6f7314d92018fb4268a76668a536f133599b91edd48759442"}, + {file = "psutil-7.2.1.tar.gz", hash = "sha256:f7583aec590485b43ca601dd9cea0dcd65bd7bb21d30ef4ddbf4ea6b5ed1bdd3"}, ] [package.extras] -dev = ["abi3audit", "black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pyreadline ; os_name == \"nt\"", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-xdist", "pywin32 ; os_name == \"nt\" and platform_python_implementation != \"PyPy\"", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "validate-pyproject[all]", "virtualenv", "vulture", "wheel", "wheel ; os_name == \"nt\" and platform_python_implementation != \"PyPy\"", "wmi ; os_name == \"nt\" and platform_python_implementation != \"PyPy\""] -test = ["pytest", "pytest-instafail", "pytest-subtests", "pytest-xdist", "pywin32 ; os_name == \"nt\" and platform_python_implementation != \"PyPy\"", "setuptools", "wheel ; os_name == \"nt\" and platform_python_implementation != \"PyPy\"", "wmi ; os_name == \"nt\" and platform_python_implementation != \"PyPy\""] +dev = ["abi3audit", "black", "check-manifest", "coverage", "packaging", "psleak", "pylint", "pyperf", "pypinfo", "pytest", "pytest-cov", "pytest-instafail", "pytest-xdist", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "validate-pyproject[all]", "virtualenv", "vulture", "wheel"] +test = ["psleak", "pytest", "pytest-instafail", "pytest-xdist", "setuptools"] [[package]] name = "ptyprocess" @@ -3486,14 +3697,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyparsing" -version = "3.2.5" +version = "3.3.1" description = "pyparsing - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.9" groups = ["main", "examples"] files = [ - {file = "pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e"}, - {file = "pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6"}, + {file = "pyparsing-3.3.1-py3-none-any.whl", hash = "sha256:023b5e7e5520ad96642e2c6db4cb683d3970bd640cdf7115049a6e9c3682df82"}, + {file = "pyparsing-3.3.1.tar.gz", hash = "sha256:47fad0f17ac1e2cad3de3b458570fbc9b03560aa029ed5e16ee5554da9a2251c"}, ] [package.extras] @@ -3824,20 +4035,21 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "referencing" -version = "0.35.1" +version = "0.36.2" description = "JSON Referencing + Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] markers = "python_version < \"3.11\"" files = [ - {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, - {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, + {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, + {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, ] [package.dependencies] attrs = ">=22.2.0" rpds-py = ">=0.7.0" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "referencing" @@ -3926,242 +4138,294 @@ testing = ["pytest (>=8.3.5)"] [[package]] name = "rpds-py" -version = "0.20.1" +version = "0.27.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] markers = "python_version < \"3.11\"" files = [ - {file = "rpds_py-0.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a649dfd735fff086e8a9d0503a9f0c7d01b7912a333c7ae77e1515c08c146dad"}, - {file = "rpds_py-0.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f16bc1334853e91ddaaa1217045dd7be166170beec337576818461268a3de67f"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14511a539afee6f9ab492b543060c7491c99924314977a55c98bfa2ee29ce78c"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3ccb8ac2d3c71cda472b75af42818981bdacf48d2e21c36331b50b4f16930163"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c142b88039b92e7e0cb2552e8967077e3179b22359e945574f5e2764c3953dcf"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f19169781dddae7478a32301b499b2858bc52fc45a112955e798ee307e294977"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13c56de6518e14b9bf6edde23c4c39dac5b48dcf04160ea7bce8fca8397cdf86"}, - {file = "rpds_py-0.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:925d176a549f4832c6f69fa6026071294ab5910e82a0fe6c6228fce17b0706bd"}, - {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78f0b6877bfce7a3d1ff150391354a410c55d3cdce386f862926a4958ad5ab7e"}, - {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3dd645e2b0dcb0fd05bf58e2e54c13875847687d0b71941ad2e757e5d89d4356"}, - {file = "rpds_py-0.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4f676e21db2f8c72ff0936f895271e7a700aa1f8d31b40e4e43442ba94973899"}, - {file = "rpds_py-0.20.1-cp310-none-win32.whl", hash = "sha256:648386ddd1e19b4a6abab69139b002bc49ebf065b596119f8f37c38e9ecee8ff"}, - {file = "rpds_py-0.20.1-cp310-none-win_amd64.whl", hash = "sha256:d9ecb51120de61e4604650666d1f2b68444d46ae18fd492245a08f53ad2b7711"}, - {file = "rpds_py-0.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:762703bdd2b30983c1d9e62b4c88664df4a8a4d5ec0e9253b0231171f18f6d75"}, - {file = "rpds_py-0.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0b581f47257a9fce535c4567782a8976002d6b8afa2c39ff616edf87cbeff712"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842c19a6ce894493563c3bd00d81d5100e8e57d70209e84d5491940fdb8b9e3a"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42cbde7789f5c0bcd6816cb29808e36c01b960fb5d29f11e052215aa85497c93"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c8e9340ce5a52f95fa7d3b552b35c7e8f3874d74a03a8a69279fd5fca5dc751"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ba6f89cac95c0900d932c9efb7f0fb6ca47f6687feec41abcb1bd5e2bd45535"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a916087371afd9648e1962e67403c53f9c49ca47b9680adbeef79da3a7811b0"}, - {file = "rpds_py-0.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:200a23239781f46149e6a415f1e870c5ef1e712939fe8fa63035cd053ac2638e"}, - {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:58b1d5dd591973d426cbb2da5e27ba0339209832b2f3315928c9790e13f159e8"}, - {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6b73c67850ca7cae0f6c56f71e356d7e9fa25958d3e18a64927c2d930859b8e4"}, - {file = "rpds_py-0.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d8761c3c891cc51e90bc9926d6d2f59b27beaf86c74622c8979380a29cc23ac3"}, - {file = "rpds_py-0.20.1-cp311-none-win32.whl", hash = "sha256:cd945871335a639275eee904caef90041568ce3b42f402c6959b460d25ae8732"}, - {file = "rpds_py-0.20.1-cp311-none-win_amd64.whl", hash = "sha256:7e21b7031e17c6b0e445f42ccc77f79a97e2687023c5746bfb7a9e45e0921b84"}, - {file = "rpds_py-0.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:36785be22066966a27348444b40389f8444671630063edfb1a2eb04318721e17"}, - {file = "rpds_py-0.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:142c0a5124d9bd0e2976089484af5c74f47bd3298f2ed651ef54ea728d2ea42c"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbddc10776ca7ebf2a299c41a4dde8ea0d8e3547bfd731cb87af2e8f5bf8962d"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15a842bb369e00295392e7ce192de9dcbf136954614124a667f9f9f17d6a216f"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be5ef2f1fc586a7372bfc355986226484e06d1dc4f9402539872c8bb99e34b01"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbcf360c9e3399b056a238523146ea77eeb2a596ce263b8814c900263e46031a"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecd27a66740ffd621d20b9a2f2b5ee4129a56e27bfb9458a3bcc2e45794c96cb"}, - {file = "rpds_py-0.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0b937b2a1988f184a3e9e577adaa8aede21ec0b38320d6009e02bd026db04fa"}, - {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6889469bfdc1eddf489729b471303739bf04555bb151fe8875931f8564309afc"}, - {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:19b73643c802f4eaf13d97f7855d0fb527fbc92ab7013c4ad0e13a6ae0ed23bd"}, - {file = "rpds_py-0.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c6afcf2338e7f374e8edc765c79fbcb4061d02b15dd5f8f314a4af2bdc7feb5"}, - {file = "rpds_py-0.20.1-cp312-none-win32.whl", hash = "sha256:dc73505153798c6f74854aba69cc75953888cf9866465196889c7cdd351e720c"}, - {file = "rpds_py-0.20.1-cp312-none-win_amd64.whl", hash = "sha256:8bbe951244a838a51289ee53a6bae3a07f26d4e179b96fc7ddd3301caf0518eb"}, - {file = "rpds_py-0.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6ca91093a4a8da4afae7fe6a222c3b53ee4eef433ebfee4d54978a103435159e"}, - {file = "rpds_py-0.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b9c2fe36d1f758b28121bef29ed1dee9b7a2453e997528e7d1ac99b94892527c"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f009c69bc8c53db5dfab72ac760895dc1f2bc1b62ab7408b253c8d1ec52459fc"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6740a3e8d43a32629bb9b009017ea5b9e713b7210ba48ac8d4cb6d99d86c8ee8"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32b922e13d4c0080d03e7b62991ad7f5007d9cd74e239c4b16bc85ae8b70252d"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe00a9057d100e69b4ae4a094203a708d65b0f345ed546fdef86498bf5390982"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fe9b04b6fa685bd39237d45fad89ba19e9163a1ccaa16611a812e682913496"}, - {file = "rpds_py-0.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aa7ac11e294304e615b43f8c441fee5d40094275ed7311f3420d805fde9b07b4"}, - {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aa97af1558a9bef4025f8f5d8c60d712e0a3b13a2fe875511defc6ee77a1ab7"}, - {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:483b29f6f7ffa6af845107d4efe2e3fa8fb2693de8657bc1849f674296ff6a5a"}, - {file = "rpds_py-0.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37fe0f12aebb6a0e3e17bb4cd356b1286d2d18d2e93b2d39fe647138458b4bcb"}, - {file = "rpds_py-0.20.1-cp313-none-win32.whl", hash = "sha256:a624cc00ef2158e04188df5e3016385b9353638139a06fb77057b3498f794782"}, - {file = "rpds_py-0.20.1-cp313-none-win_amd64.whl", hash = "sha256:b71b8666eeea69d6363248822078c075bac6ed135faa9216aa85f295ff009b1e"}, - {file = "rpds_py-0.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5b48e790e0355865197ad0aca8cde3d8ede347831e1959e158369eb3493d2191"}, - {file = "rpds_py-0.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3e310838a5801795207c66c73ea903deda321e6146d6f282e85fa7e3e4854804"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249280b870e6a42c0d972339e9cc22ee98730a99cd7f2f727549af80dd5a963"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e79059d67bea28b53d255c1437b25391653263f0e69cd7dec170d778fdbca95e"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b431c777c9653e569986ecf69ff4a5dba281cded16043d348bf9ba505486f36"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da584ff96ec95e97925174eb8237e32f626e7a1a97888cdd27ee2f1f24dd0ad8"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a0629ec053fc013808a85178524e3cb63a61dbc35b22499870194a63578fb9"}, - {file = "rpds_py-0.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fbf15aff64a163db29a91ed0868af181d6f68ec1a3a7d5afcfe4501252840bad"}, - {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:07924c1b938798797d60c6308fa8ad3b3f0201802f82e4a2c41bb3fafb44cc28"}, - {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4a5a844f68776a7715ecb30843b453f07ac89bad393431efbf7accca3ef599c1"}, - {file = "rpds_py-0.20.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:518d2ca43c358929bf08f9079b617f1c2ca6e8848f83c1225c88caeac46e6cbc"}, - {file = "rpds_py-0.20.1-cp38-none-win32.whl", hash = "sha256:3aea7eed3e55119635a74bbeb80b35e776bafccb70d97e8ff838816c124539f1"}, - {file = "rpds_py-0.20.1-cp38-none-win_amd64.whl", hash = "sha256:7dca7081e9a0c3b6490a145593f6fe3173a94197f2cb9891183ef75e9d64c425"}, - {file = "rpds_py-0.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b41b6321805c472f66990c2849e152aff7bc359eb92f781e3f606609eac877ad"}, - {file = "rpds_py-0.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a90c373ea2975519b58dece25853dbcb9779b05cc46b4819cb1917e3b3215b6"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16d4477bcb9fbbd7b5b0e4a5d9b493e42026c0bf1f06f723a9353f5153e75d30"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84b8382a90539910b53a6307f7c35697bc7e6ffb25d9c1d4e998a13e842a5e83"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4888e117dd41b9d34194d9e31631af70d3d526efc363085e3089ab1a62c32ed1"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5265505b3d61a0f56618c9b941dc54dc334dc6e660f1592d112cd103d914a6db"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e75ba609dba23f2c95b776efb9dd3f0b78a76a151e96f96cc5b6b1b0004de66f"}, - {file = "rpds_py-0.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1791ff70bc975b098fe6ecf04356a10e9e2bd7dc21fa7351c1742fdeb9b4966f"}, - {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d126b52e4a473d40232ec2052a8b232270ed1f8c9571aaf33f73a14cc298c24f"}, - {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c14937af98c4cc362a1d4374806204dd51b1e12dded1ae30645c298e5a5c4cb1"}, - {file = "rpds_py-0.20.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3d089d0b88996df627693639d123c8158cff41c0651f646cd8fd292c7da90eaf"}, - {file = "rpds_py-0.20.1-cp39-none-win32.whl", hash = "sha256:653647b8838cf83b2e7e6a0364f49af96deec64d2a6578324db58380cff82aca"}, - {file = "rpds_py-0.20.1-cp39-none-win_amd64.whl", hash = "sha256:fa41a64ac5b08b292906e248549ab48b69c5428f3987b09689ab2441f267d04d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a07ced2b22f0cf0b55a6a510078174c31b6d8544f3bc00c2bcee52b3d613f74"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:68cb0a499f2c4a088fd2f521453e22ed3527154136a855c62e148b7883b99f9a"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa3060d885657abc549b2a0f8e1b79699290e5d83845141717c6c90c2df38311"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95f3b65d2392e1c5cec27cff08fdc0080270d5a1a4b2ea1d51d5f4a2620ff08d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2cc3712a4b0b76a1d45a9302dd2f53ff339614b1c29603a911318f2357b04dd2"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d4eea0761e37485c9b81400437adb11c40e13ef513375bbd6973e34100aeb06"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f5179583d7a6cdb981151dd349786cbc318bab54963a192692d945dd3f6435d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fbb0ffc754490aff6dabbf28064be47f0f9ca0b9755976f945214965b3ace7e"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a94e52537a0e0a85429eda9e49f272ada715506d3b2431f64b8a3e34eb5f3e75"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:92b68b79c0da2a980b1c4197e56ac3dd0c8a149b4603747c4378914a68706979"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:93da1d3db08a827eda74356f9f58884adb254e59b6664f64cc04cdff2cc19b0d"}, - {file = "rpds_py-0.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:754bbed1a4ca48479e9d4182a561d001bbf81543876cdded6f695ec3d465846b"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ca449520e7484534a2a44faf629362cae62b660601432d04c482283c47eaebab"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:9c4cb04a16b0f199a8c9bf807269b2f63b7b5b11425e4a6bd44bd6961d28282c"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63804105143c7e24cee7db89e37cb3f3941f8e80c4379a0b355c52a52b6780"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55cd1fa4ecfa6d9f14fbd97ac24803e6f73e897c738f771a9fe038f2f11ff07c"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f8f741b6292c86059ed175d80eefa80997125b7c478fb8769fd9ac8943a16c0"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fc212779bf8411667234b3cdd34d53de6c2b8b8b958e1e12cb473a5f367c338"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ad56edabcdb428c2e33bbf24f255fe2b43253b7d13a2cdbf05de955217313e6"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a3a1e9ee9728b2c1734f65d6a1d376c6f2f6fdcc13bb007a08cc4b1ff576dc5"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e13de156137b7095442b288e72f33503a469aa1980ed856b43c353ac86390519"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:07f59760ef99f31422c49038964b31c4dfcfeb5d2384ebfc71058a7c9adae2d2"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:59240685e7da61fb78f65a9f07f8108e36a83317c53f7b276b4175dc44151684"}, - {file = "rpds_py-0.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:83cba698cfb3c2c5a7c3c6bac12fe6c6a51aae69513726be6411076185a8b24a"}, - {file = "rpds_py-0.20.1.tar.gz", hash = "sha256:e1791c4aabd117653530dccd24108fa03cc6baf21f58b950d0a73c3b3b29a350"}, + {file = "rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef"}, + {file = "rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9"}, + {file = "rpds_py-0.27.1-cp310-cp310-win32.whl", hash = "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4"}, + {file = "rpds_py-0.27.1-cp310-cp310-win_amd64.whl", hash = "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1"}, + {file = "rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881"}, + {file = "rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948"}, + {file = "rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39"}, + {file = "rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15"}, + {file = "rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746"}, + {file = "rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90"}, + {file = "rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998"}, + {file = "rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39"}, + {file = "rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594"}, + {file = "rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502"}, + {file = "rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b"}, + {file = "rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002"}, + {file = "rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3"}, + {file = "rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83"}, + {file = "rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d"}, + {file = "rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228"}, + {file = "rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7"}, + {file = "rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688"}, + {file = "rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797"}, + {file = "rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334"}, + {file = "rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675"}, + {file = "rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3"}, + {file = "rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456"}, + {file = "rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3"}, + {file = "rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2"}, + {file = "rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0"}, + {file = "rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a"}, + {file = "rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772"}, + {file = "rpds_py-0.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c918c65ec2e42c2a78d19f18c553d77319119bf43aa9e2edf7fb78d624355527"}, + {file = "rpds_py-0.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fea2b1a922c47c51fd07d656324531adc787e415c8b116530a1d29c0516c62d"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbf94c58e8e0cd6b6f38d8de67acae41b3a515c26169366ab58bdca4a6883bb8"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2a8fed130ce946d5c585eddc7c8eeef0051f58ac80a8ee43bd17835c144c2cc"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:037a2361db72ee98d829bc2c5b7cc55598ae0a5e0ec1823a56ea99374cfd73c1"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5281ed1cc1d49882f9997981c88df1a22e140ab41df19071222f7e5fc4e72125"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd50659a069c15eef8aa3d64bbef0d69fd27bb4a50c9ab4f17f83a16cbf8905"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:c4b676c4ae3921649a15d28ed10025548e9b561ded473aa413af749503c6737e"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:079bc583a26db831a985c5257797b2b5d3affb0386e7ff886256762f82113b5e"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4e44099bd522cba71a2c6b97f68e19f40e7d85399de899d66cdb67b32d7cb786"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e202e6d4188e53c6661af813b46c37ca2c45e497fc558bacc1a7630ec2695aec"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f41f814b8eaa48768d1bb551591f6ba45f87ac76899453e8ccd41dba1289b04b"}, + {file = "rpds_py-0.27.1-cp39-cp39-win32.whl", hash = "sha256:9e71f5a087ead99563c11fdaceee83ee982fd39cf67601f4fd66cb386336ee52"}, + {file = "rpds_py-0.27.1-cp39-cp39-win_amd64.whl", hash = "sha256:71108900c9c3c8590697244b9519017a400d9ba26a36c48381b3f64743a44aab"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa8933159edc50be265ed22b401125c9eebff3171f570258854dbce3ecd55475"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a50431bf02583e21bf273c71b89d710e7a710ad5e39c725b14e685610555926f"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78af06ddc7fe5cc0e967085a9115accee665fb912c22a3f54bad70cc65b05fe6"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70d0738ef8fee13c003b100c2fbd667ec4f133468109b3472d249231108283a3"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2f6fd8a1cea5bbe599b6e78a6e5ee08db434fc8ffea51ff201c8765679698b3"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8177002868d1426305bb5de1e138161c2ec9eb2d939be38291d7c431c4712df8"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:008b839781d6c9bf3b6a8984d1d8e56f0ec46dc56df61fd669c49b58ae800400"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:a55b9132bb1ade6c734ddd2759c8dc132aa63687d259e725221f106b83a0e485"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a46fdec0083a26415f11d5f236b79fa1291c32aaa4a17684d82f7017a1f818b1"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8a63b640a7845f2bdd232eb0d0a4a2dd939bcdd6c57e6bb134526487f3160ec5"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7e32721e5d4922deaaf963469d795d5bde6093207c52fec719bd22e5d1bedbc4"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c426b99a068601b5f4623573df7a7c3d72e87533a2dd2253353a03e7502566c"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4fc9b7fe29478824361ead6e14e4f5aed570d477e06088826537e202d25fe859"}, + {file = "rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8"}, ] [[package]] name = "rpds-py" -version = "0.28.0" +version = "0.30.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" groups = ["dev"] markers = "python_version >= \"3.11\"" files = [ - {file = "rpds_py-0.28.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7b6013db815417eeb56b2d9d7324e64fcd4fa289caeee6e7a78b2e11fc9b438a"}, - {file = "rpds_py-0.28.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a4c6b05c685c0c03f80dabaeb73e74218c49deea965ca63f76a752807397207"}, - {file = "rpds_py-0.28.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4794c6c3fbe8f9ac87699b131a1f26e7b4abcf6d828da46a3a52648c7930eba"}, - {file = "rpds_py-0.28.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2e8456b6ee5527112ff2354dd9087b030e3429e43a74f480d4a5ca79d269fd85"}, - {file = "rpds_py-0.28.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:beb880a9ca0a117415f241f66d56025c02037f7c4efc6fe59b5b8454f1eaa50d"}, - {file = "rpds_py-0.28.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6897bebb118c44b38c9cb62a178e09f1593c949391b9a1a6fe777ccab5934ee7"}, - {file = "rpds_py-0.28.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b553dd06e875249fd43efd727785efb57a53180e0fde321468222eabbeaafa"}, - {file = "rpds_py-0.28.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:f0b2044fdddeea5b05df832e50d2a06fe61023acb44d76978e1b060206a8a476"}, - {file = "rpds_py-0.28.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05cf1e74900e8da73fa08cc76c74a03345e5a3e37691d07cfe2092d7d8e27b04"}, - {file = "rpds_py-0.28.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:efd489fec7c311dae25e94fe7eeda4b3d06be71c68f2cf2e8ef990ffcd2cd7e8"}, - {file = "rpds_py-0.28.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ada7754a10faacd4f26067e62de52d6af93b6d9542f0df73c57b9771eb3ba9c4"}, - {file = "rpds_py-0.28.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c2a34fd26588949e1e7977cfcbb17a9a42c948c100cab890c6d8d823f0586457"}, - {file = "rpds_py-0.28.0-cp310-cp310-win32.whl", hash = "sha256:f9174471d6920cbc5e82a7822de8dfd4dcea86eb828b04fc8c6519a77b0ee51e"}, - {file = "rpds_py-0.28.0-cp310-cp310-win_amd64.whl", hash = "sha256:6e32dd207e2c4f8475257a3540ab8a93eff997abfa0a3fdb287cae0d6cd874b8"}, - {file = "rpds_py-0.28.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:03065002fd2e287725d95fbc69688e0c6daf6c6314ba38bdbaa3895418e09296"}, - {file = "rpds_py-0.28.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28ea02215f262b6d078daec0b45344c89e161eab9526b0d898221d96fdda5f27"}, - {file = "rpds_py-0.28.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25dbade8fbf30bcc551cb352376c0ad64b067e4fc56f90e22ba70c3ce205988c"}, - {file = "rpds_py-0.28.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c03002f54cc855860bfdc3442928ffdca9081e73b5b382ed0b9e8efe6e5e205"}, - {file = "rpds_py-0.28.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9699fa7990368b22032baf2b2dce1f634388e4ffc03dfefaaac79f4695edc95"}, - {file = "rpds_py-0.28.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9b06fe1a75e05e0713f06ea0c89ecb6452210fd60e2f1b6ddc1067b990e08d9"}, - {file = "rpds_py-0.28.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9f83e7b326a3f9ec3ef84cda98fb0a74c7159f33e692032233046e7fd15da2"}, - {file = "rpds_py-0.28.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:0d3259ea9ad8743a75a43eb7819324cdab393263c91be86e2d1901ee65c314e0"}, - {file = "rpds_py-0.28.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a7548b345f66f6695943b4ef6afe33ccd3f1b638bd9afd0f730dd255c249c9e"}, - {file = "rpds_py-0.28.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9a40040aa388b037eb39416710fbcce9443498d2eaab0b9b45ae988b53f5c67"}, - {file = "rpds_py-0.28.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f60c7ea34e78c199acd0d3cda37a99be2c861dd2b8cf67399784f70c9f8e57d"}, - {file = "rpds_py-0.28.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1571ae4292649100d743b26d5f9c63503bb1fedf538a8f29a98dce2d5ba6b4e6"}, - {file = "rpds_py-0.28.0-cp311-cp311-win32.whl", hash = "sha256:5cfa9af45e7c1140af7321fa0bef25b386ee9faa8928c80dc3a5360971a29e8c"}, - {file = "rpds_py-0.28.0-cp311-cp311-win_amd64.whl", hash = "sha256:dd8d86b5d29d1b74100982424ba53e56033dc47720a6de9ba0259cf81d7cecaa"}, - {file = "rpds_py-0.28.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e27d3a5709cc2b3e013bf93679a849213c79ae0573f9b894b284b55e729e120"}, - {file = "rpds_py-0.28.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6b4f28583a4f247ff60cd7bdda83db8c3f5b05a7a82ff20dd4b078571747708f"}, - {file = "rpds_py-0.28.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d678e91b610c29c4b3d52a2c148b641df2b4676ffe47c59f6388d58b99cdc424"}, - {file = "rpds_py-0.28.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e819e0e37a44a78e1383bf1970076e2ccc4dc8c2bbaa2f9bd1dc987e9afff628"}, - {file = "rpds_py-0.28.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5ee514e0f0523db5d3fb171f397c54875dbbd69760a414dccf9d4d7ad628b5bd"}, - {file = "rpds_py-0.28.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f3fa06d27fdcee47f07a39e02862da0100cb4982508f5ead53ec533cd5fe55e"}, - {file = "rpds_py-0.28.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46959ef2e64f9e4a41fc89aa20dbca2b85531f9a72c21099a3360f35d10b0d5a"}, - {file = "rpds_py-0.28.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8455933b4bcd6e83fde3fefc987a023389c4b13f9a58c8d23e4b3f6d13f78c84"}, - {file = "rpds_py-0.28.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ad50614a02c8c2962feebe6012b52f9802deec4263946cddea37aaf28dd25a66"}, - {file = "rpds_py-0.28.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e5deca01b271492553fdb6c7fd974659dce736a15bae5dad7ab8b93555bceb28"}, - {file = "rpds_py-0.28.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:735f8495a13159ce6a0d533f01e8674cec0c57038c920495f87dcb20b3ddb48a"}, - {file = "rpds_py-0.28.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:961ca621ff10d198bbe6ba4957decca61aa2a0c56695384c1d6b79bf61436df5"}, - {file = "rpds_py-0.28.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2374e16cc9131022e7d9a8f8d65d261d9ba55048c78f3b6e017971a4f5e6353c"}, - {file = "rpds_py-0.28.0-cp312-cp312-win32.whl", hash = "sha256:d15431e334fba488b081d47f30f091e5d03c18527c325386091f31718952fe08"}, - {file = "rpds_py-0.28.0-cp312-cp312-win_amd64.whl", hash = "sha256:a410542d61fc54710f750d3764380b53bf09e8c4edbf2f9141a82aa774a04f7c"}, - {file = "rpds_py-0.28.0-cp312-cp312-win_arm64.whl", hash = "sha256:1f0cfd1c69e2d14f8c892b893997fa9a60d890a0c8a603e88dca4955f26d1edd"}, - {file = "rpds_py-0.28.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e9e184408a0297086f880556b6168fa927d677716f83d3472ea333b42171ee3b"}, - {file = "rpds_py-0.28.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:edd267266a9b0448f33dc465a97cfc5d467594b600fe28e7fa2f36450e03053a"}, - {file = "rpds_py-0.28.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85beb8b3f45e4e32f6802fb6cd6b17f615ef6c6a52f265371fb916fae02814aa"}, - {file = "rpds_py-0.28.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2412be8d00a1b895f8ad827cc2116455196e20ed994bb704bf138fe91a42724"}, - {file = "rpds_py-0.28.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf128350d384b777da0e68796afdcebc2e9f63f0e9f242217754e647f6d32491"}, - {file = "rpds_py-0.28.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2036d09b363aa36695d1cc1a97b36865597f4478470b0697b5ee9403f4fe399"}, - {file = "rpds_py-0.28.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8e1e9be4fa6305a16be628959188e4fd5cd6f1b0e724d63c6d8b2a8adf74ea6"}, - {file = "rpds_py-0.28.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0a403460c9dd91a7f23fc3188de6d8977f1d9603a351d5db6cf20aaea95b538d"}, - {file = "rpds_py-0.28.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d7366b6553cdc805abcc512b849a519167db8f5e5c3472010cd1228b224265cb"}, - {file = "rpds_py-0.28.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b43c6a3726efd50f18d8120ec0551241c38785b68952d240c45ea553912ac41"}, - {file = "rpds_py-0.28.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0cb7203c7bc69d7c1585ebb33a2e6074492d2fc21ad28a7b9d40457ac2a51ab7"}, - {file = "rpds_py-0.28.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a52a5169c664dfb495882adc75c304ae1d50df552fbd68e100fdc719dee4ff9"}, - {file = "rpds_py-0.28.0-cp313-cp313-win32.whl", hash = "sha256:2e42456917b6687215b3e606ab46aa6bca040c77af7df9a08a6dcfe8a4d10ca5"}, - {file = "rpds_py-0.28.0-cp313-cp313-win_amd64.whl", hash = "sha256:e0a0311caedc8069d68fc2bf4c9019b58a2d5ce3cd7cb656c845f1615b577e1e"}, - {file = "rpds_py-0.28.0-cp313-cp313-win_arm64.whl", hash = "sha256:04c1b207ab8b581108801528d59ad80aa83bb170b35b0ddffb29c20e411acdc1"}, - {file = "rpds_py-0.28.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f296ea3054e11fc58ad42e850e8b75c62d9a93a9f981ad04b2e5ae7d2186ff9c"}, - {file = "rpds_py-0.28.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5a7306c19b19005ad98468fcefeb7100b19c79fc23a5f24a12e06d91181193fa"}, - {file = "rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5d9b86aa501fed9862a443c5c3116f6ead8bc9296185f369277c42542bd646b"}, - {file = "rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e5bbc701eff140ba0e872691d573b3d5d30059ea26e5785acba9132d10c8c31d"}, - {file = "rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5690671cd672a45aa8616d7374fdf334a1b9c04a0cac3c854b1136e92374fe"}, - {file = "rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9f1d92ecea4fa12f978a367c32a5375a1982834649cdb96539dcdc12e609ab1a"}, - {file = "rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d252db6b1a78d0a3928b6190156042d54c93660ce4d98290d7b16b5296fb7cc"}, - {file = "rpds_py-0.28.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d61b355c3275acb825f8777d6c4505f42b5007e357af500939d4a35b19177259"}, - {file = "rpds_py-0.28.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:acbe5e8b1026c0c580d0321c8aae4b0a1e1676861d48d6e8c6586625055b606a"}, - {file = "rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8aa23b6f0fc59b85b4c7d89ba2965af274346f738e8d9fc2455763602e62fd5f"}, - {file = "rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7b14b0c680286958817c22d76fcbca4800ddacef6f678f3a7c79a1fe7067fe37"}, - {file = "rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bcf1d210dfee61a6c86551d67ee1031899c0fdbae88b2d44a569995d43797712"}, - {file = "rpds_py-0.28.0-cp313-cp313t-win32.whl", hash = "sha256:3aa4dc0fdab4a7029ac63959a3ccf4ed605fee048ba67ce89ca3168da34a1342"}, - {file = "rpds_py-0.28.0-cp313-cp313t-win_amd64.whl", hash = "sha256:7b7d9d83c942855e4fdcfa75d4f96f6b9e272d42fffcb72cd4bb2577db2e2907"}, - {file = "rpds_py-0.28.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:dcdcb890b3ada98a03f9f2bb108489cdc7580176cb73b4f2d789e9a1dac1d472"}, - {file = "rpds_py-0.28.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f274f56a926ba2dc02976ca5b11c32855cbd5925534e57cfe1fda64e04d1add2"}, - {file = "rpds_py-0.28.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fe0438ac4a29a520ea94c8c7f1754cdd8feb1bc490dfda1bfd990072363d527"}, - {file = "rpds_py-0.28.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a358a32dd3ae50e933347889b6af9a1bdf207ba5d1a3f34e1a38cd3540e6733"}, - {file = "rpds_py-0.28.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e80848a71c78aa328fefaba9c244d588a342c8e03bda518447b624ea64d1ff56"}, - {file = "rpds_py-0.28.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f586db2e209d54fe177e58e0bc4946bea5fb0102f150b1b2f13de03e1f0976f8"}, - {file = "rpds_py-0.28.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ae8ee156d6b586e4292491e885d41483136ab994e719a13458055bec14cf370"}, - {file = "rpds_py-0.28.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:a805e9b3973f7e27f7cab63a6b4f61d90f2e5557cff73b6e97cd5b8540276d3d"}, - {file = "rpds_py-0.28.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5d3fd16b6dc89c73a4da0b4ac8b12a7ecc75b2864b95c9e5afed8003cb50a728"}, - {file = "rpds_py-0.28.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6796079e5d24fdaba6d49bda28e2c47347e89834678f2bc2c1b4fc1489c0fb01"}, - {file = "rpds_py-0.28.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:76500820c2af232435cbe215e3324c75b950a027134e044423f59f5b9a1ba515"}, - {file = "rpds_py-0.28.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bbdc5640900a7dbf9dd707fe6388972f5bbd883633eb68b76591044cfe346f7e"}, - {file = "rpds_py-0.28.0-cp314-cp314-win32.whl", hash = "sha256:adc8aa88486857d2b35d75f0640b949759f79dc105f50aa2c27816b2e0dd749f"}, - {file = "rpds_py-0.28.0-cp314-cp314-win_amd64.whl", hash = "sha256:66e6fa8e075b58946e76a78e69e1a124a21d9a48a5b4766d15ba5b06869d1fa1"}, - {file = "rpds_py-0.28.0-cp314-cp314-win_arm64.whl", hash = "sha256:a6fe887c2c5c59413353b7c0caff25d0e566623501ccfff88957fa438a69377d"}, - {file = "rpds_py-0.28.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7a69df082db13c7070f7b8b1f155fa9e687f1d6aefb7b0e3f7231653b79a067b"}, - {file = "rpds_py-0.28.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b1cde22f2c30ebb049a9e74c5374994157b9b70a16147d332f89c99c5960737a"}, - {file = "rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5338742f6ba7a51012ea470bd4dc600a8c713c0c72adaa0977a1b1f4327d6592"}, - {file = "rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1460ebde1bcf6d496d80b191d854adedcc619f84ff17dc1c6d550f58c9efbba"}, - {file = "rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e3eb248f2feba84c692579257a043a7699e28a77d86c77b032c1d9fbb3f0219c"}, - {file = "rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3bbba5def70b16cd1c1d7255666aad3b290fbf8d0fe7f9f91abafb73611a91"}, - {file = "rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3114f4db69ac5a1f32e7e4d1cbbe7c8f9cf8217f78e6e002cedf2d54c2a548ed"}, - {file = "rpds_py-0.28.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4b0cb8a906b1a0196b863d460c0222fb8ad0f34041568da5620f9799b83ccf0b"}, - {file = "rpds_py-0.28.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf681ac76a60b667106141e11a92a3330890257e6f559ca995fbb5265160b56e"}, - {file = "rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1e8ee6413cfc677ce8898d9cde18cc3a60fc2ba756b0dec5b71eb6eb21c49fa1"}, - {file = "rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b3072b16904d0b5572a15eb9d31c1954e0d3227a585fc1351aa9878729099d6c"}, - {file = "rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b670c30fd87a6aec281c3c9896d3bae4b205fd75d79d06dc87c2503717e46092"}, - {file = "rpds_py-0.28.0-cp314-cp314t-win32.whl", hash = "sha256:8014045a15b4d2b3476f0a287fcc93d4f823472d7d1308d47884ecac9e612be3"}, - {file = "rpds_py-0.28.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7a4e59c90d9c27c561eb3160323634a9ff50b04e4f7820600a2beb0ac90db578"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f5e7101145427087e493b9c9b959da68d357c28c562792300dd21a095118ed16"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:31eb671150b9c62409a888850aaa8e6533635704fe2b78335f9aaf7ff81eec4d"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48b55c1f64482f7d8bd39942f376bfdf2f6aec637ee8c805b5041e14eeb771db"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24743a7b372e9a76171f6b69c01aedf927e8ac3e16c474d9fe20d552a8cb45c7"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:389c29045ee8bbb1627ea190b4976a310a295559eaf9f1464a1a6f2bf84dde78"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23690b5827e643150cf7b49569679ec13fe9a610a15949ed48b85eb7f98f34ec"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f0c9266c26580e7243ad0d72fc3e01d6b33866cfab5084a6da7576bcf1c4f72"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4c6c4db5d73d179746951486df97fd25e92396be07fc29ee8ff9a8f5afbdfb27"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3b695a8fa799dd2cfdb4804b37096c5f6dba1ac7f48a7fbf6d0485bcd060316"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:6aa1bfce3f83baf00d9c5fcdbba93a3ab79958b4c7d7d1f55e7fe68c20e63912"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b0f9dceb221792b3ee6acb5438eb1f02b0cb2c247796a72b016dcc92c6de829"}, - {file = "rpds_py-0.28.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5d0145edba8abd3db0ab22b5300c99dc152f5c9021fab861be0f0544dc3cbc5f"}, - {file = "rpds_py-0.28.0.tar.gz", hash = "sha256:abd4df20485a0983e2ca334a216249b6186d6e3c1627e106651943dbdb791aea"}, + {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, + {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221"}, + {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7"}, + {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff"}, + {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7"}, + {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139"}, + {file = "rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464"}, + {file = "rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169"}, + {file = "rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425"}, + {file = "rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d"}, + {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed"}, + {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85"}, + {file = "rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c"}, + {file = "rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825"}, + {file = "rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229"}, + {file = "rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad"}, + {file = "rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6"}, + {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e"}, + {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394"}, + {file = "rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf"}, + {file = "rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b"}, + {file = "rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e"}, + {file = "rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2"}, + {file = "rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e"}, + {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d"}, + {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7"}, + {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31"}, + {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95"}, + {file = "rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d"}, + {file = "rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15"}, + {file = "rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1"}, + {file = "rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a"}, + {file = "rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9"}, + {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0"}, + {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94"}, + {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08"}, + {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27"}, + {file = "rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6"}, + {file = "rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d"}, + {file = "rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0"}, + {file = "rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07"}, + {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f"}, + {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65"}, + {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f"}, + {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53"}, + {file = "rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed"}, + {file = "rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950"}, + {file = "rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6"}, + {file = "rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb"}, + {file = "rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8"}, + {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5"}, + {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404"}, + {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856"}, + {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40"}, + {file = "rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0"}, + {file = "rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4"}, + {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e"}, + {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, ] [[package]] @@ -4317,14 +4581,14 @@ test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6 [[package]] name = "send2trash" -version = "1.8.3" +version = "2.0.0" description = "Send file to trash natively under Mac OS X, Windows and Linux" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*" groups = ["dev"] files = [ - {file = "Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9"}, - {file = "Send2Trash-1.8.3.tar.gz", hash = "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf"}, + {file = "send2trash-2.0.0-py3-none-any.whl", hash = "sha256:e70d5ce41dbb890882cc78bc25d137478330b39a391e756fadf82e34da4d85b8"}, + {file = "send2trash-2.0.0.tar.gz", hash = "sha256:1761421da3f9930bfe51ed7c45343948573383ad4c27e3acebc91be324e7770d"}, ] [package.extras] @@ -4500,28 +4764,16 @@ files = [ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - [[package]] name = "soupsieve" -version = "2.8" +version = "2.8.1" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c"}, - {file = "soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f"}, + {file = "soupsieve-2.8.1-py3-none-any.whl", hash = "sha256:a11fe2a6f3d76ab3cf2de04eb339c1be5b506a8a47f2ceb6d139803177f85434"}, + {file = "soupsieve-2.8.1.tar.gz", hash = "sha256:4cf733bc50fa805f5df4b8ef4740fc0e0fa6218cf3006269afd3f9d6d80fd350"}, ] [[package]] @@ -4566,26 +4818,6 @@ docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] -[[package]] -name = "tinycss2" -version = "1.2.1" -description = "A tiny CSS parser" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -markers = "python_version < \"3.11\"" -files = [ - {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, - {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, -] - -[package.dependencies] -webencodings = ">=0.4" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "pytest"] - [[package]] name = "tinycss2" version = "1.4.0" @@ -4593,7 +4825,6 @@ description = "A tiny CSS parser" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version >= \"3.11\"" files = [ {file = "tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"}, {file = "tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"}, @@ -4673,24 +4904,24 @@ files = [ [[package]] name = "tornado" -version = "6.5.2" +version = "6.5.4" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2436822940d37cde62771cff8774f4f00b3c8024fe482e16ca8387b8a2724db6"}, - {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:583a52c7aa94ee046854ba81d9ebb6c81ec0fd30386d96f7640c96dad45a03ef"}, - {file = "tornado-6.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0fe179f28d597deab2842b86ed4060deec7388f1fd9c1b4a41adf8af058907e"}, - {file = "tornado-6.5.2-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b186e85d1e3536d69583d2298423744740986018e393d0321df7340e71898882"}, - {file = "tornado-6.5.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e792706668c87709709c18b353da1f7662317b563ff69f00bab83595940c7108"}, - {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:06ceb1300fd70cb20e43b1ad8aaee0266e69e7ced38fa910ad2e03285009ce7c"}, - {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:74db443e0f5251be86cbf37929f84d8c20c27a355dd452a5cfa2aada0d001ec4"}, - {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b5e735ab2889d7ed33b32a459cac490eda71a1ba6857b0118de476ab6c366c04"}, - {file = "tornado-6.5.2-cp39-abi3-win32.whl", hash = "sha256:c6f29e94d9b37a95013bb669616352ddb82e3bfe8326fccee50583caebc8a5f0"}, - {file = "tornado-6.5.2-cp39-abi3-win_amd64.whl", hash = "sha256:e56a5af51cc30dd2cae649429af65ca2f6571da29504a07995175df14c18f35f"}, - {file = "tornado-6.5.2-cp39-abi3-win_arm64.whl", hash = "sha256:d6c33dc3672e3a1f3618eb63b7ef4683a7688e7b9e6e8f0d9aa5726360a004af"}, - {file = "tornado-6.5.2.tar.gz", hash = "sha256:ab53c8f9a0fa351e2c0741284e06c7a45da86afb544133201c5cc8578eb076a0"}, + {file = "tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9"}, + {file = "tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843"}, + {file = "tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17"}, + {file = "tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335"}, + {file = "tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f"}, + {file = "tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84"}, + {file = "tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f"}, + {file = "tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8"}, + {file = "tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1"}, + {file = "tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc"}, + {file = "tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1"}, + {file = "tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7"}, ] [[package]] @@ -4745,14 +4976,14 @@ files = [ [[package]] name = "tzdata" -version = "2025.2" +version = "2025.3" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main", "dev"] files = [ - {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, - {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, + {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, + {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, ] [[package]] @@ -4800,21 +5031,21 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.5.0" +version = "2.6.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, - {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, + {file = "urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd"}, + {file = "urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797"}, ] [package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "wcwidth" @@ -4835,11 +5066,25 @@ description = "A library for working with the color formats defined by HTML and optional = false python-versions = ">=3.9" groups = ["dev"] +markers = "python_version < \"3.11\"" files = [ {file = "webcolors-24.11.1-py3-none-any.whl", hash = "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9"}, {file = "webcolors-24.11.1.tar.gz", hash = "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6"}, ] +[[package]] +name = "webcolors" +version = "25.10.0" +description = "A library for working with the color formats defined by HTML and CSS." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d"}, + {file = "webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf"}, +] + [[package]] name = "webencodings" version = "0.5.1" @@ -4871,27 +5116,27 @@ test = ["pytest", "websockets"] [[package]] name = "widgetsnbextension" -version = "4.0.14" +version = "4.0.15" description = "Jupyter interactive widgets for Jupyter Notebook" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "widgetsnbextension-4.0.14-py3-none-any.whl", hash = "sha256:4875a9eaf72fbf5079dc372a51a9f268fc38d46f767cbf85c43a36da5cb9b575"}, - {file = "widgetsnbextension-4.0.14.tar.gz", hash = "sha256:a3629b04e3edb893212df862038c7232f62973373869db5084aed739b437b5af"}, + {file = "widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366"}, + {file = "widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9"}, ] [[package]] name = "zipp" -version = "3.20.2" +version = "3.23.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main", "dev", "examples"] markers = "python_version == \"3.9\"" files = [ - {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, - {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, + {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, + {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, ] [package.extras] @@ -4899,10 +5144,10 @@ check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \" cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = "^3.9" -content-hash = "4a2f0b1c5894aa64fd619bb5d21363a7895b6ed5f38683efd03c91db167555f4" +content-hash = "276682e947433f51c108591f32d55ee08df61859dce7806b1bfc6bd0e7a35519" diff --git a/pyproject.toml b/pyproject.toml index 6c722a2..64e6cc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ numpy = ">=1.16.5" scipy = ">=1.6" unified-momentum-model = {git = "https://github.com/Howland-Lab/Unified-Momentum-Model.git"} pyyaml = "^6.0.1" -floris = "^4.5.1" +floris = {git = "https://github.com/misi9170/floris.git", branch = "feature/user-def-op-mod"} [tool.poetry.group.dev.dependencies] black = { extras = ["jupyter"], version = "^23.9.1" } From a6f936d955e6a4a0d499052fad7c1511e431f609 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 7 Jan 2026 17:14:26 -0500 Subject: [PATCH 04/50] floris interface tests finished --- MITRotor/FlorisInterface/FlorisInterface.py | 72 +++--- examples/example_05_floris_integration.ipynb | 253 ------------------- examples/example_05_floris_integration.py | 9 +- tests/test_floris_interface.py | 118 +++++++++ 4 files changed, 152 insertions(+), 300 deletions(-) delete mode 100644 examples/example_05_floris_integration.ipynb create mode 100644 tests/test_floris_interface.py diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index d4285fa..9d97191 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -21,6 +21,14 @@ def default_bem_factory(): geometry=BEMGeometry(Nr=10, Ntheta=20), ) +def default_pitch_csv(): + module_dir = os.path.dirname(__file__) + return os.path.join(module_dir, "pitch_15mw.csv") + +def default_tsr_csv(): + module_dir = os.path.dirname(__file__) + return os.path.join(module_dir, "tsr_15mw.csv") + def csv_to_interp(csv_file): # read in csv data = np.loadtxt(csv_file, delimiter=",", skiprows=1) @@ -32,7 +40,7 @@ def csv_to_interp(csv_file): x = x[idx] y = y[idx] # return interpolator for y - return interp1d(x, y, kind="linear", fill_value=0.0001, bounds_error=False) + return interp1d(x, y, kind="linear", fill_value="extrapolate", bounds_error=False) @define class MITRotorTurbine(BaseOperationModel): @@ -41,20 +49,20 @@ class MITRotorTurbine(BaseOperationModel): """ # user can define a BEM model if they want a different rotor, momentum model, or geometry bem_model = field(init = True, factory = default_bem_factory, type = BEM) + + # user can define csv paths for pitch and tsr values + pitch_csv = field(init = True, factory = default_pitch_csv, type = str) + tsr_csv = field(init = True, factory = default_tsr_csv, type = str) + + # create interp objects based on pitch and tsr csvs + _pitch_interp = field(init=False, default=None, type = interp1d, repr = False) + _tsr_interp = field(init=False, default=None, type = interp1d, repr = False) + # save most recent solution by unique floris arguments _last_key = field(init=False, default=None, type = bytes) _a = field(init=False, default=None, type = NDArrayFloat) _Ct = field(init=False, default=None, type = NDArrayFloat) _power = field(init=False, default=None, type = NDArrayFloat) - # user can define csv paths for pitch and tsr values - module_dir = os.path.dirname(__file__) - default_pitch_csv = os.path.join(module_dir, "pitch_15mw.csv") - default_tsr_csv = os.path.join(module_dir, "tsr_15mw.csv") - pitch_csv = field(init = True, default = default_pitch_csv, type = str) - tsr_csv = field(init = True, default= default_tsr_csv, type = str) - # create interp objects based on pitch and tsr csvs - _pitch_interp = field(init=False, default=None, type = interp1d, repr = False) - _tsr_interp = field(init=False, default=None, type = interp1d, repr = False) def __attrs_post_init__(self): self._pitch_interp = csv_to_interp(self.pitch_csv) @@ -65,20 +73,20 @@ def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_an return velocities.tobytes(), yaw_angles.tobytes(), tilt_angles.tobytes() def _update_solution(self, - power_thrust_table: dict, velocities: NDArrayFloat, air_density: float, yaw_angles: NDArrayFloat, tilt_angles: NDArrayFloat, average_method: str = "cubic-mean", cubature_weights: NDArrayFloat | None = None, - **kwargs, + **_, ): - n_findex, n_turbines = yaw_angles.shape # create cache key for current inputs key = self._get_state_key(velocities, yaw_angles, tilt_angles) # TODO: add more inputs # update solution if conditions are different if key != self._last_key: + n_findex, n_turbines = yaw_angles.shape + # save new key and clear fields self._last_key = key self._a = np.empty((n_findex, n_turbines), dtype=floris_float_type) @@ -91,39 +99,23 @@ def _update_solution(self, method=average_method, cubature_weights=cubature_weights, ) - # update effective velocities for air density - rotor_effective_velocities = rotor_velocity_air_density_correction( - velocities=rotor_average_velocities, - air_density=air_density, - ref_air_density=power_thrust_table["ref_air_density"] - ) + # calculate rotor area + rotor_area = np.pi * self.bem_model.rotor.R**2 # loop over flow conditions for findex in range(n_findex): for tindex in range(n_turbines): - vel = rotor_effective_velocities[findex, tindex] + # get setpoints + vel = rotor_average_velocities[findex, tindex] yaw, tilt = np.deg2rad(yaw_angles[findex, tindex]), np.deg2rad(tilt_angles[findex, tindex]) - pitch_val = np.deg2rad(self._pitch_interp(vel)) - tsr_val = self._tsr_interp(vel) - bem_sol = self.bem_model(pitch_val, tsr_val, yaw = yaw, tilt = tilt) + pitch = np.deg2rad(self._pitch_interp(vel)) + tsr = self._tsr_interp(vel) + # solve BEM + bem_sol = self.bem_model(pitch, tsr, yaw = yaw, tilt = tilt) + # get induction and thrust coeff self._a[findex, tindex] = bem_sol.a() self._Ct[findex, tindex] = bem_sol.Ct() - # calculate power - rotor_area = np.pi * self.bem_model.rotor.R**2 - rotor_uinfty = vel * np.cos(calc_eff_yaw(yaw, tilt)) - - # Construct power interpolant - power_interpolator = interp1d( - power_thrust_table["wind_speed"], - power_thrust_table["power"], - fill_value=0.0, - bounds_error=False, - ) - - # Compute power - power = power_interpolator(rotor_uinfty) * 1e3 # --> I am not sure the rotor_uinfty is the right value... - self._power[findex, tindex] = power # it seems like using Cp (below) should be correct... plot power interpolator... - # self._power[findex, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_uinfty)**3 - + # compute power + self._power[findex, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (vel)**3 return def power(self, **kwargs) -> NDArrayFloat: diff --git a/examples/example_05_floris_integration.ipynb b/examples/example_05_floris_integration.ipynb deleted file mode 100644 index 9552036..0000000 --- a/examples/example_05_floris_integration.ipynb +++ /dev/null @@ -1,253 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 7, - "id": "eb249327", - "metadata": {}, - "outputs": [], - "source": [ - "from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, MITRotorTurbine\n", - "from floris import FlorisModel, TimeSeries\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "9cc53ad8", - "metadata": {}, - "outputs": [], - "source": [ - "def check_interp(tsr_csv, pitch_csv):\n", - " tsr_interp = csv_to_interp(tsr_csv)\n", - " pitch_interp = csv_to_interp(pitch_csv)\n", - " print(type(pitch_interp))\n", - " # interp values\n", - " x_interp_vals = np.linspace(0, 25, num=100)\n", - " tsr_interp_vals = tsr_interp(x_interp_vals)\n", - " pitch_interp_vals = pitch_interp(x_interp_vals)\n", - " # actual values\n", - " tsr_data = np.loadtxt(tsr_csv, delimiter=\",\", skiprows=1)\n", - " pitch_data = np.loadtxt(pitch_csv, delimiter=\",\", skiprows=1)\n", - " # plot\n", - " plt.plot(x_interp_vals, tsr_interp_vals, label = \"TSR Interpolation\")\n", - " plt.plot(x_interp_vals, pitch_interp_vals, label = \"Pitch Interpolation\")\n", - " plt.scatter(tsr_data[:, 0], tsr_data[:, 1], label = \"TSR Data\")\n", - " plt.scatter(pitch_data[:, 0], pitch_data[:, 1], label = \"Pitch Data\")\n", - " plt.legend()" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "08c83a7f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "tsr_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/tsr_15mw.csv\"\n", - "pitch_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/pitch_15mw.csv\"\n", - "check_interp(tsr_15mw_csv, pitch_15mw_csv)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "51835dd1", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "tsr_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/tsr_5mw.csv\"\n", - "pitch_15mw_csv = \"/Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/pitch_5mw.csv\"\n", - "check_interp(tsr_15mw_csv, pitch_15mw_csv)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "2a93558a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Powers [W]:\n", - " [[1753954.45917917 354990.76412771]\n", - " [3417797.00509157 737171.66537995]\n", - " [5000000. 4927707.14320011]] \n", - "\n", - "Thrust coefficients [-]:\n", - " [[0.78715145 0.9353766 ]\n", - " [0.78387889 0.86092059]\n", - " [0.55092883 0.74517368]] \n", - "\n", - "Axial induction factors [-]:\n", - " [[0.26932244 0.37289433]\n", - " [0.26755586 0.31353324]\n", - " [0.16493614 0.24759837]] \n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/sky/Library/Caches/pypoetry/virtualenvs/mitrotor-l4Gn_-ln-py3.12/lib/python3.12/site-packages/floris/core/flow_field.py:172: UserWarning: 'where' used without 'out', expect unitialized memory in output. If this is intentional, use out=None.\n", - " * np.power(\n" - ] - } - ], - "source": [ - "from floris.core.turbine.unified_momentum_model import UnifiedMomentumModelTurbine\n", - "from floris import FlorisModel\n", - "\n", - "fmodel = FlorisModel(\"defaults\")\n", - "\n", - "time_series = TimeSeries(\n", - " wind_directions=np.array([270.0, 270.0, 280.0]),\n", - " wind_speeds=np.array([8.0, 10.0, 12.0]),\n", - " turbulence_intensities=np.array([0.06, 0.06, 0.06]),\n", - ")\n", - "\n", - "fmodel.set(\n", - " layout_x = [0.0, 500.0],\n", - " layout_y = [0.0, 0.0],\n", - " wind_data=time_series,\n", - ")\n", - "\n", - "fmodel.run()\n", - "\n", - "print(\"Powers [W]:\\n\", fmodel.get_turbine_powers(), \"\\n\")\n", - "print(\"Thrust coefficients [-]:\\n\", fmodel.get_turbine_thrust_coefficients(), \"\\n\")\n", - "print(\"Axial induction factors [-]:\\n\", fmodel.get_turbine_axial_induction_factors(), \"\\n\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c7d9b5ae", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Powers [W]:\n", - " [[ -80385.81346439 35955.07110895]\n", - " [-151917.60066 85753.35035653]\n", - " [-190271.12187713 332785.69634393]] \n", - "\n", - "Thrust coefficients [-]:\n", - " [[0.73380279 0.74621482]\n", - " [0.66198028 0.74239241]\n", - " [0.41175519 0.5029464 ]] \n", - "\n", - "Axial induction factors [-]:\n", - " [[0.34782061 0.35018336]\n", - " [0.30308838 0.35179638]\n", - " [0.18725075 0.22345784]] \n", - "\n" - ] - } - ], - "source": [ - "from floris import FlorisModel, TimeSeries\n", - "\n", - "fmodel = FlorisModel(\"defaults\")\n", - "\n", - "time_series = TimeSeries(\n", - " wind_directions=np.array([270.0, 270.0, 280.0]),\n", - " wind_speeds=np.array([8.0, 10.0, 12.0]),\n", - " turbulence_intensities=np.array([0.06, 0.06, 0.06]),\n", - ")\n", - "\n", - "yaw_angles = np.array([\n", - " [10.0, 0.0], # condition 1\n", - " [10.0, 0.0], # condition 2\n", - " [10.0, 0.0], # condition 3\n", - "])\n", - "\n", - "fmodel.set(\n", - " layout_x = [0.0, 500.0],\n", - " layout_y = [0.0, 0.0],\n", - " wind_data = time_series,\n", - " yaw_angles = yaw_angles\n", - ")\n", - "\n", - "fmodel.set_operation_model(MITRotorTurbine())\n", - "fmodel.run()\n", - "\n", - "print(\"Powers [W]:\\n\", fmodel.get_turbine_powers(), \"\\n\")\n", - "print(\"Thrust coefficients [-]:\\n\", fmodel.get_turbine_thrust_coefficients(), \"\\n\")\n", - "print(\"Axial induction factors [-]:\\n\", fmodel.get_turbine_axial_induction_factors(), \"\\n\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "de761cdd", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "mitrotor-l4Gn_-ln-py3.12", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.11" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/example_05_floris_integration.py b/examples/example_05_floris_integration.py index 093b0cb..71b4c6a 100644 --- a/examples/example_05_floris_integration.py +++ b/examples/example_05_floris_integration.py @@ -1,10 +1,8 @@ -from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, MITRotorTurbine +import numpy as np from floris import FlorisModel, TimeSeries +from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, MITRotorTurbine from floris.core.turbine.unified_momentum_model import UnifiedMomentumModelTurbine -import numpy as np -import matplotlib.pyplot as plt -from floris import FlorisModel, TimeSeries fmodel = FlorisModel("defaults") time_series = TimeSeries( @@ -25,9 +23,6 @@ yaw_angles = yaw_angles ) fmodel.set_operation_model(UnifiedMomentumModelTurbine) - -# fmodel.set_operation_model(MITRotorTurbine()) - fmodel.run() print("Powers [W]:\n", fmodel.get_turbine_powers(), "\n") diff --git a/tests/test_floris_interface.py b/tests/test_floris_interface.py new file mode 100644 index 0000000..2d335fb --- /dev/null +++ b/tests/test_floris_interface.py @@ -0,0 +1,118 @@ +import numpy as np +import pytest +from importlib.resources import files +from numpy.testing import assert_almost_equal, assert_allclose +from floris import FlorisModel, TimeSeries +from MITRotor.FlorisInterface import FlorisInterface +from MITRotor.FlorisInterface.FlorisInterface import default_bem_factory, default_pitch_csv, default_tsr_csv +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, csv_to_interp + + +def test_pitch_tsr_interpolation(): + # get 15MW CSV file paths + pitch_csv = files("MITRotor.FlorisInterface") / "pitch_15mw.csv" + tsr_csv = files("MITRotor.FlorisInterface") / "tsr_15mw.csv" + pitch_csv = str(pitch_csv) + tsr_csv = str(tsr_csv) + # create interpolators + tsr_interp = csv_to_interp(tsr_csv) + pitch_interp = csv_to_interp(pitch_csv) + + # load raw CSV data + tsr_data = np.loadtxt(tsr_csv, delimiter=",", skiprows=1) + pitch_data = np.loadtxt(pitch_csv, delimiter=",", skiprows=1) + tsr_ws, tsr_vals = tsr_data[:, 0], tsr_data[:, 1] + pitch_ws, pitch_vals = pitch_data[:, 0], pitch_data[:, 1] + + # interpolator reproduces raw data + assert_allclose(tsr_interp(tsr_ws), tsr_vals, rtol=1e-12, atol=1e-12) + assert_allclose(pitch_interp(pitch_ws), pitch_vals, rtol=1e-12, atol=1e-12) + + # reasonable values + x_interp_vals = np.linspace(0.0, 25.0, 100) + tsr_interp_vals = tsr_interp(x_interp_vals) + pitch_interp_vals = pitch_interp(x_interp_vals) + assert np.all(np.isfinite(tsr_interp_vals)) + assert np.all(np.isfinite(pitch_interp_vals)) + assert np.all(tsr_interp_vals > 0.0) + assert np.all(pitch_interp_vals >= -10.0) # deg, loose bound + assert np.all(pitch_interp_vals <= 40.0) + + +# compute MITRotor BEM outputs directly +def compute_mitrotor_cp_ct_a(wind_speeds, yaw_deg = 0.0, tilt_deg = 0.0): + bem_model = default_bem_factory() # default BEM (IEA15MW) used in floris interface + pitch_interp = csv_to_interp(default_pitch_csv()) # IEA15MW pitch curve + tsr_interp = csv_to_interp(default_tsr_csv()) # IEA15MW tsr curve + + n = len(wind_speeds) + Ct = np.empty(n) + a = np.empty(n) + for i, ws in enumerate(wind_speeds): + pitch = np.deg2rad(pitch_interp(ws)) + tsr = tsr_interp(ws) + sol = bem_model(pitch, tsr, yaw=np.deg2rad(yaw_deg), tilt = np.deg2rad(tilt_deg)) + Ct[i] = sol.Ct() + a[i] = sol.a() + + return Ct, a + +@pytest.mark.parametrize("n_turbines", [1, 2]) +def test_mitrotor_floris_wind_speeds(n_turbines): + wind_speeds = np.array([6.0, 8.0, 10.0, 12.0]) + wind_dirs = np.full_like(wind_speeds, 270.0) + turbulence_intensity = np.zeros_like(wind_speeds) + + time_series = TimeSeries( + wind_speeds=wind_speeds, + wind_directions=wind_dirs, + turbulence_intensities=turbulence_intensity, + ) + + layout_x = np.linspace(0.0, 500.0 * (n_turbines - 1), n_turbines) + layout_y = np.zeros_like(layout_x) + + fmodel = FlorisModel("defaults") + fmodel.set(layout_x=layout_x, layout_y=layout_y, wind_data=time_series) + fmodel.set_operation_model(MITRotorTurbine()) + + fmodel.run() + + floris_Ct = fmodel.get_turbine_thrust_coefficients() + floris_a = fmodel.get_turbine_axial_induction_factors() + + mit_Ct, mit_a = compute_mitrotor_cp_ct_a(wind_speeds) + + # First turbine matches MITRotor BEM (<1% error) + assert_almost_equal(floris_Ct[:, 0], mit_Ct, decimal=2) + assert_almost_equal(floris_a[:, 0], mit_a, decimal=2) + + if n_turbines > 1: + # first turbine produces more power than the second (wake effects) + floris_power = fmodel.get_turbine_powers() + assert np.all(floris_power[:, 0] > floris_power[:, 1]) + + # yawing the first turbine decreases first turbine power and increases second turbine power + fmodel = FlorisModel("defaults") + yaw_angles = np.tile(np.array([5.0, 0.0]), (4,1)) + fmodel.set(layout_x=layout_x, layout_y=layout_y, wind_data=time_series, yaw_angles = yaw_angles) + fmodel.set_operation_model(MITRotorTurbine()) + fmodel.run() + yawed_floris_power = fmodel.get_turbine_powers() + assert np.all(floris_power[:, 0] > yawed_floris_power[:, 0]) + assert np.all(floris_power[:, 1] < yawed_floris_power[:, 1]) + + # TODO: uncomment if tilt is able to be set for Floris + # tilting the first turbine decreases first turbine power and increases second turbine power + # fmodel = FlorisModel("defaults") + # tilt_angles = np.tile(np.array([5.0, 0.0]), (4,1)) + # fmodel.set(layout_x=layout_x, layout_y=layout_y, wind_data=time_series, tilt_angles = tilt_angles) + # fmodel.set_operation_model(MITRotorTurbine()) + # fmodel.run() + # tilted_floris_power = fmodel.get_turbine_powers() + # assert np.all(floris_power[:, 0] > tilted_floris_power[:, 0]) + # assert np.all(floris_power[:, 1] < tilted_floris_power[:, 1]) + + # # yawing and tilting turbines is equivalent + # assert_almost_equal(yawed_floris_power[:, 0], tilted_floris_power[:, 0], decimal=4) + # assert_almost_equal(yawed_floris_power[:, 1], tilted_floris_power[:, 1], decimal=4) From 6dd4da0578a2b7d4fedd4f42db0903896e02c0a1 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 7 Jan 2026 17:41:11 -0500 Subject: [PATCH 05/50] Add files to poetry --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 64e6cc7..8dfd92d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,14 +31,14 @@ matplotlib = "^3.7.3" polars = "^0.19.2" tqdm = "^4.66.1" - [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" - [tool.black] line-length = 120 [tool.ruff] line-length = 120 + +include = ["MITRotor/FlorisInterface/*.csv"] From 71c808ac7f0bd92c2369f779c6a3fcd24e551b8f Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 7 Jan 2026 17:48:20 -0500 Subject: [PATCH 06/50] Save needed CSV files on GitHub --- .gitignore | 5 +- MITRotor/FlorisInterface/pitch_15mw.csv | 33 +++++++++++++ MITRotor/FlorisInterface/tsr_15mw.csv | 33 +++++++++++++ examples/example_05_floris_integration.py | 9 ++-- poetry.lock | 59 +++++++++++++++++++---- 5 files changed, 124 insertions(+), 15 deletions(-) create mode 100644 MITRotor/FlorisInterface/pitch_15mw.csv create mode 100644 MITRotor/FlorisInterface/tsr_15mw.csv diff --git a/.gitignore b/.gitignore index f729f42..7455b55 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # Created by https://www.toptal.com/developers/gitignore/api/python # Edit at https://www.toptal.com/developers/gitignore?templates=python - fig fig* *.mat @@ -14,6 +13,10 @@ fig* *.tar *.whl +# Allow these CSVs needed for the floris interface +!MITRotor/FlorisInterface/pitch_15mw.csv +!MITRotor/FlorisInterface/tsr_15mw.csv + ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/MITRotor/FlorisInterface/pitch_15mw.csv b/MITRotor/FlorisInterface/pitch_15mw.csv new file mode 100644 index 0000000..ad33a54 --- /dev/null +++ b/MITRotor/FlorisInterface/pitch_15mw.csv @@ -0,0 +1,33 @@ +wind_speed, pitch +2.9492833517089307, 3.876651982378855 +3.2800441014332966, 3.876651982378855 +3.6990077177508267, 3.876651982378855 +4.117971334068358, 3.436123348017621 +4.911797133406836, 2.8193832599118944 +5.507166482910694, 2.026431718061674 +6.080485115766262, 1.3215859030837005 +6.896361631753032, 0.0881057268722467 +7.844542447629548, 0 +8.7045203969129, 0 +9.432194046306504, 0 +10.115766262403529, 1.8502202643171808 +10.77728776185226, 3.1718061674008813 +11.1742006615215, 3.6123348017621146 +11.637265711135612, 4.845814977973569 +12.078280044101433, 5.991189427312776 +12.717750826901874, 7.48898678414097 +13.864388092613009, 9.60352422907489 +14.547960308710033, 10.748898678414097 +15.231532524807056, 11.718061674008812 +16.245865490628447, 13.215859030837006 +17.039691289966925, 14.273127753303966 +17.723263506063944, 15.154185022026432 +18.362734288864388, 15.947136563876652 +19.04630650496141, 16.740088105726873 +19.906284454244762, 17.709251101321588 +20.45755237045204, 18.325991189427313 +21.604189636163174, 19.559471365638768 +22.640573318632853, 20.61674008810573 +23.721058434399115, 21.762114537444933 +24.40463065049614, 22.46696035242291 +25.02205071664829, 22.995594713656388 \ No newline at end of file diff --git a/MITRotor/FlorisInterface/tsr_15mw.csv b/MITRotor/FlorisInterface/tsr_15mw.csv new file mode 100644 index 0000000..096640a --- /dev/null +++ b/MITRotor/FlorisInterface/tsr_15mw.csv @@ -0,0 +1,33 @@ +wind_speed, tsr +2.993384785005513, 20.792951541850222 +3.2138919514884234, 19.383259911894275 +3.478500551267916, 18.061674008810574 +3.7210584343991178, 16.82819383259912 +4.007717750826902, 15.418502202643174 +4.294377067254686, 14.537444933920705 +4.603087100330761, 13.480176211453745 +4.955898566703418, 12.687224669603525 +5.352811466372657, 11.629955947136564 +5.83792723263506, 10.572687224669604 +6.2348401323043, 9.955947136563877 +6.65380374862183, 9.33920704845815 +7.006615214994487, 8.986784140969164 +7.9547960308710035, 8.986784140969164 +8.880926130099228, 8.81057268722467 +9.807056229327454, 8.986784140969164 +10.689084895259096, 8.986784140969164 +11.681367144432194, 8.370044052863436 +13.114663726571113, 7.312775330396476 +14.283351708930539, 6.607929515418503 +15.143329658213892, 6.255506607929516 +16.245865490628447, 5.814977973568282 +16.863285556780596, 5.638766519823789 +17.67916207276736, 5.462555066079296 +18.80374862183021, 5.110132158590309 +19.928335170893053, 4.845814977973569 +20.87651598676957, 4.581497797356828 +21.49393605292172, 4.493392070484582 +22.39801543550165, 4.229074889867841 +23.16979051819184, 4.052863436123348 +23.96361631753032, 3.9647577092511015 +24.933847850055127, 3.788546255506608 \ No newline at end of file diff --git a/examples/example_05_floris_integration.py b/examples/example_05_floris_integration.py index 71b4c6a..ae3bf2f 100644 --- a/examples/example_05_floris_integration.py +++ b/examples/example_05_floris_integration.py @@ -1,8 +1,9 @@ +import re import numpy as np +from pathlib import Path +import matplotlib.pyplot as plt from floris import FlorisModel, TimeSeries -from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, MITRotorTurbine -from floris.core.turbine.unified_momentum_model import UnifiedMomentumModelTurbine - +from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, default_bem_factory, MITRotorTurbine fmodel = FlorisModel("defaults") time_series = TimeSeries( @@ -22,7 +23,7 @@ wind_data = time_series, yaw_angles = yaw_angles ) -fmodel.set_operation_model(UnifiedMomentumModelTurbine) +fmodel.set_operation_model(MITRotorTurbine) fmodel.run() print("Powers [W]:\n", fmodel.get_turbine_powers(), "\n") diff --git a/poetry.lock b/poetry.lock index c90a865..d31bbbb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "anyio" -version = "4.12.0" +version = "4.12.1" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "anyio-4.12.0-py3-none-any.whl", hash = "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb"}, - {file = "anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0"}, + {file = "anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c"}, + {file = "anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703"}, ] [package.dependencies] @@ -1511,6 +1511,7 @@ description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.9" groups = ["dev"] +markers = "python_version < \"3.11\"" files = [ {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"}, {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"}, @@ -1535,6 +1536,38 @@ webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] +[[package]] +name = "jsonschema" +version = "4.26.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, + {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} +rfc3987-syntax = {version = ">=1.1.0", optional = true, markers = "extra == \"format-nongpl\""} +rpds-py = ">=0.25.0" +uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] + [[package]] name = "jsonschema-specifications" version = "2025.9.1" @@ -3196,16 +3229,22 @@ ppft = ">=1.7.7" [[package]] name = "pathspec" -version = "0.12.1" +version = "1.0.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, + {file = "pathspec-1.0.1-py3-none-any.whl", hash = "sha256:8870061f22c58e6d83463cfce9a7dd6eca0512c772c1001fb09ac64091816721"}, + {file = "pathspec-1.0.1.tar.gz", hash = "sha256:e2769b508d0dd47b09af6ee2c75b2744a2cb1f474ae4b1494fd6a1b7a841613c"}, ] +[package.extras] +hyperscan = ["hyperscan (>=0.7)"] +optional = ["typing-extensions (>=4)"] +re2 = ["google-re2 (>=1.1)"] +tests = ["pytest (>=9)", "typing-extensions (>=4.15)"] + [[package]] name = "pexpect" version = "4.9.0" @@ -5031,14 +5070,14 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.6.2" +version = "2.6.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd"}, - {file = "urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797"}, + {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, + {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, ] [package.extras] From b7a69b107f097dc32b6c5f6f1bd5eef7bb65440e Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 7 Jan 2026 17:53:38 -0500 Subject: [PATCH 07/50] Remove | that isn't python 3.9 compatible --- MITRotor/FlorisInterface/FlorisInterface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 9d97191..ea717b4 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -1,7 +1,7 @@ import numpy as np import os from attrs import define, field -from typing import Literal, Optional +from typing import Optional from scipy.interpolate import interp1d # FLORIS Imports from floris.type_dec import floris_float_type, NDArrayFloat @@ -78,7 +78,7 @@ def _update_solution(self, yaw_angles: NDArrayFloat, tilt_angles: NDArrayFloat, average_method: str = "cubic-mean", - cubature_weights: NDArrayFloat | None = None, + cubature_weights: Optional[NDArrayFloat] = None, **_, ): # create cache key for current inputs From f696c689af0664c9c0fb97c2e3f45f6dccb40ef5 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 7 Jan 2026 17:58:40 -0500 Subject: [PATCH 08/50] Remove non-python 3.9 compatible file call --- tests/test_floris_interface.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/test_floris_interface.py b/tests/test_floris_interface.py index 2d335fb..46f0fe8 100644 --- a/tests/test_floris_interface.py +++ b/tests/test_floris_interface.py @@ -1,6 +1,6 @@ import numpy as np import pytest -from importlib.resources import files +import os from numpy.testing import assert_almost_equal, assert_allclose from floris import FlorisModel, TimeSeries from MITRotor.FlorisInterface import FlorisInterface @@ -10,10 +10,12 @@ def test_pitch_tsr_interpolation(): # get 15MW CSV file paths - pitch_csv = files("MITRotor.FlorisInterface") / "pitch_15mw.csv" - tsr_csv = files("MITRotor.FlorisInterface") / "tsr_15mw.csv" - pitch_csv = str(pitch_csv) - tsr_csv = str(tsr_csv) + module_dir = os.path.dirname(__file__) # tests/ + pitch_csv = os.path.join(module_dir, "..", "MITRotor", "FlorisInterface", "pitch_15mw.csv") + tsr_csv = os.path.join(module_dir, "..", "MITRotor", "FlorisInterface", "tsr_15mw.csv") + pitch_csv = os.path.abspath(pitch_csv) + tsr_csv = os.path.abspath(tsr_csv) + # create interpolators tsr_interp = csv_to_interp(tsr_csv) pitch_interp = csv_to_interp(pitch_csv) From 1a8b424fad05130d331eaccfe1827df1c04fbf96 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 7 Jan 2026 19:17:03 -0500 Subject: [PATCH 09/50] Add larger example and clean up comments --- MITRotor/FlorisInterface/FlorisInterface.py | 17 ++- examples/example_05_floris_integration.py | 120 +++++++++++++++++++- 2 files changed, 128 insertions(+), 9 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index ea717b4..4358caa 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -14,17 +14,21 @@ from MITRotor.BEMSolver import BEM from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw +# default rotor if none provided by user (IEA 15MW) def default_bem_factory(): return BEM( rotor=IEA15MW(), momentum_model=UnifiedMomentum(averaging="rotor"), geometry=BEMGeometry(Nr=10, Ntheta=20), ) - +# pitch vs windspeed curve if none provided by user +# for IEA 15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) def default_pitch_csv(): module_dir = os.path.dirname(__file__) return os.path.join(module_dir, "pitch_15mw.csv") +# tsr vs windspeed curve if none provided by user +# for IEA 15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) def default_tsr_csv(): module_dir = os.path.dirname(__file__) return os.path.join(module_dir, "tsr_15mw.csv") @@ -40,7 +44,7 @@ def csv_to_interp(csv_file): x = x[idx] y = y[idx] # return interpolator for y - return interp1d(x, y, kind="linear", fill_value="extrapolate", bounds_error=False) + return interp1d(x, y, kind="linear", fill_value="extrapolate", bounds_error=False) # TODO: should fill_value be extrapolate? @define class MITRotorTurbine(BaseOperationModel): @@ -65,11 +69,12 @@ class MITRotorTurbine(BaseOperationModel): _power = field(init=False, default=None, type = NDArrayFloat) def __attrs_post_init__(self): + # creates interpolation objects self._pitch_interp = csv_to_interp(self.pitch_csv) self._tsr_interp = csv_to_interp(self.tsr_csv) def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_angles: np.ndarray) -> tuple: - # Fast, deterministic, and explicit + # saves key to uniquely identify farm state -> avoids re-solving for calls to power, thrust, and induction for same state return velocities.tobytes(), yaw_angles.tobytes(), tilt_angles.tobytes() def _update_solution(self, @@ -82,7 +87,7 @@ def _update_solution(self, **_, ): # create cache key for current inputs - key = self._get_state_key(velocities, yaw_angles, tilt_angles) # TODO: add more inputs + key = self._get_state_key(velocities, yaw_angles, tilt_angles) # update solution if conditions are different if key != self._last_key: n_findex, n_turbines = yaw_angles.shape @@ -99,9 +104,11 @@ def _update_solution(self, method=average_method, cubature_weights=cubature_weights, ) + # calculate rotor area rotor_area = np.pi * self.bem_model.rotor.R**2 - # loop over flow conditions + + # loop over flow conditions -> TODO: should this be vectorized? for findex in range(n_findex): for tindex in range(n_turbines): # get setpoints diff --git a/examples/example_05_floris_integration.py b/examples/example_05_floris_integration.py index ae3bf2f..fd8aeb2 100644 --- a/examples/example_05_floris_integration.py +++ b/examples/example_05_floris_integration.py @@ -1,10 +1,14 @@ -import re import numpy as np +import os from pathlib import Path import matplotlib.pyplot as plt +from matplotlib import cm +from matplotlib.colors import Normalize +from matplotlib.cm import ScalarMappable from floris import FlorisModel, TimeSeries from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, default_bem_factory, MITRotorTurbine +# ------------------ run basic case -------------------------------------------------------- fmodel = FlorisModel("defaults") time_series = TimeSeries( wind_directions=np.array([270.0, 270.0, 280.0]), @@ -23,9 +27,117 @@ wind_data = time_series, yaw_angles = yaw_angles ) -fmodel.set_operation_model(MITRotorTurbine) +fmodel.set_operation_model(MITRotorTurbine()) fmodel.run() - print("Powers [W]:\n", fmodel.get_turbine_powers(), "\n") print("Thrust coefficients [-]:\n", fmodel.get_turbine_thrust_coefficients(), "\n") -print("Axial induction factors [-]:\n", fmodel.get_turbine_axial_induction_factors(), "\n") \ No newline at end of file +print("Axial induction factors [-]:\n", fmodel.get_turbine_axial_induction_factors(), "\n") + +# -------------------- plot pitch and tsr control curves, as well as CT for IEA15MW ------------------ +module_dir = os.path.dirname(__file__) # examples/ +csv_dir = os.path.join(module_dir, "..", "MITRotor", "FlorisInterface") + +wind_speeds = np.linspace(5, 25.0, 20) +wind_dirs = np.full_like(wind_speeds, 270.0) +turbulence_intensity = np.zeros_like(wind_speeds) + +# plot pitch and tsr control curves for IEA15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) +pitch_csv = os.path.join(csv_dir, "pitch_15mw.csv") +tsr_csv = os.path.join(csv_dir, "tsr_15mw.csv") +pitch_interp = csv_to_interp(pitch_csv) +tsr_interp = csv_to_interp(tsr_csv) + +# plot interpolated pitch and tsr data +fig, ax = plt.subplots(figsize=(8, 6)) +ax.scatter( + wind_speeds, + pitch_interp(wind_speeds), + s=40, + edgecolors="k", + label = "Interpolated Pitch [deg]" +) +ax.scatter( + wind_speeds, + tsr_interp(wind_speeds), + s=40, + edgecolors="k", + label = "Interpolated Tip-Speed Ratio [-]" +) + +# load and plot raw CSV data +tsr_data = np.loadtxt(tsr_csv, delimiter=",", skiprows=1) +pitch_data = np.loadtxt(pitch_csv, delimiter=",", skiprows=1) +tsr_ws, tsr_vals = tsr_data[:, 0], tsr_data[:, 1] +pitch_ws, pitch_vals = pitch_data[:, 0], pitch_data[:, 1] +ax.plot( + pitch_ws, + pitch_vals, + label = "Pitch [deg]" +) +ax.plot( + tsr_ws, + tsr_vals, + label = "Tip-Speed Ratio [-]" +) +ax.set_xlabel("Wind Speed [m/s]") +ax.set_title("IEA 15MW: Fixed Bottom Trajectories") +plt.legend() + +# compute CT from floris +fmodel = FlorisModel("defaults") + +time_series = TimeSeries( + wind_speeds=wind_speeds, + wind_directions=wind_dirs, + turbulence_intensities=turbulence_intensity, +) + +fmodel.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) +fmodel.set_operation_model(MITRotorTurbine()) +fmodel.run() +floris_Ct = fmodel.get_turbine_thrust_coefficients() + +fig, ax = plt.subplots(figsize=(8, 6)) +cmap = cm.viridis + +# plot setpoint curves for IEA15MW from figure 3.2 (https://docs.nrel.gov/docs/fy20osti/75698.pdf) +setpoint_curves = os.path.join(csv_dir, "pitch_tsr_ct_15mw.csv") +data = np.loadtxt(setpoint_curves, delimiter=",", skiprows=1) +all_cts = np.concatenate([data[:, 2], floris_Ct.flatten()]) +norm = Normalize(vmin=all_cts.min(), vmax=all_cts.max()) + +for ct in np.unique(data[:, 2]): + mask = data[:, 2] == ct + ax.plot( + data[mask, 0], + data[mask, 1], + color=cmap(norm(ct)), + linewidth=2, + label=f"Ct ≈ {ct:.3f}", + ) + +# plot FLORIS points +sc = ax.scatter( + pitch_interp(wind_speeds), + tsr_interp(wind_speeds), + c=floris_Ct, + cmap=cmap, + norm=norm, + s=40, + edgecolors="k", + label = "FLORIS with MITRotor" +) + +# colorbar that covers all Ct values +sm = ScalarMappable(norm=norm, cmap=cmap) +sm.set_array([]) +plt.colorbar(sm, ax=ax, label="$C_T$") + +# label plot +ax.set_xlabel("Pitch [deg]") +ax.set_ylabel("Tip-Speed Ratio [-]") +ax.set_title("IEA 15MW: $C_T$ Control Curves vs FLORIS/MITRotor") +ax.grid(True, alpha=0.3) +ax.legend(fontsize=9) +plt.tight_layout() +plt.show() From 92d3cda6e88c529e9860dbfb0cb11f82fb0e7493 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 7 Jan 2026 19:35:33 -0500 Subject: [PATCH 10/50] Add docstring --- MITRotor/FlorisInterface/FlorisInterface.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 4358caa..2ccdf26 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -49,7 +49,17 @@ def csv_to_interp(csv_file): @define class MITRotorTurbine(BaseOperationModel): """ - A turbine operation model that calls MITRotor. + Turbine operation model as described by Liew et al. (2024). + + Args: + bem_model (BEM): optional BEM model as defined in MITRotor, defaults to IEA15MW with UMM momentum model + pitch_csv (str): optional path to pitch trajectory based on wind speed, defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) + tsr_csv (str)): optional path to tsr trajectory based on wind speed, defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) + + Methods: + power + thrust_coefficient + axial_induction """ # user can define a BEM model if they want a different rotor, momentum model, or geometry bem_model = field(init = True, factory = default_bem_factory, type = BEM) From d4b2d1d5f215387aa480e783579d7606ad6c193e Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 8 Jan 2026 13:22:01 -0500 Subject: [PATCH 11/50] Add CT CSV file for IEA15MW --- .gitignore | 1 + .../FlorisInterface/pitch_tsr_ct_15mw.csv | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv diff --git a/.gitignore b/.gitignore index 7455b55..646f286 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ fig* # Allow these CSVs needed for the floris interface !MITRotor/FlorisInterface/pitch_15mw.csv !MITRotor/FlorisInterface/tsr_15mw.csv +!MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv ### Python ### # Byte-compiled / optimized / DLL files diff --git a/MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv b/MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv new file mode 100644 index 0000000..47c23f4 --- /dev/null +++ b/MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv @@ -0,0 +1,56 @@ +pitch,tsr,Ct +-4.952153,7.140505,0.750000 +-4.529506,7.166850,0.750000 +-4.130781,7.210757,0.750000 +-3.740032,7.254665,0.750000 +-3.325359,7.316136,0.750000 +-3.038278,7.364435,0.750000 +-2.655502,7.443469,0.750000 +-2.185008,7.553238,0.750000 +-1.866029,7.645445,0.750000 +-1.491228,7.759605,0.750000 +-1.180223,7.878156,0.750000 +-0.837321,8.014270,0.750000 +-0.454545,8.194292,0.750000 +-0.119617,8.365532,0.750000 +0.199362,8.545554,0.750000 +0.486443,8.729967,0.750000 +0.757576,8.927552,0.750000 +0.996810,9.111965,0.750000 +1.299841,9.371021,0.750000 +1.531100,9.586169,0.750000 +1.858054,9.924259,0.750000 +-4.904306,8.163557,0.900000 +-4.577352,8.225027,0.900000 +-4.242424,8.321625,0.900000 +-3.827751,8.444566,0.900000 +-3.460925,8.567508,0.900000 +-3.133971,8.699232,0.900000 +-2.759171,8.857300,0.900000 +-2.448166,8.997805,0.900000 +-2.105263,9.173436,0.900000 +-1.778309,9.353458,0.900000 +-1.395534,9.572997,0.900000 +-1.076555,9.788145,0.900000 +-0.781499,10.007684,0.900000 +-4.920255,9.353458,1.050000 +-4.649123,9.454446,1.050000 +-4.330144,9.599341,1.050000 +-4.082935,9.717892,1.050000 +-3.819777,9.845225,1.050000 +-3.548644,9.994512,1.050000 +-3.261563,10.152580,1.050000 +0.805423,7.030735,0.600000 +1.156300,7.171240,0.600000 +1.555024,7.355653,0.600000 +1.913876,7.548847,0.600000 +2.232855,7.742042,0.600000 +2.511962,7.952799,0.600000 +2.799043,8.194292,0.600000 +3.046252,8.418222,0.600000 +3.269537,8.655324,0.600000 +3.484848,8.892426,0.600000 +3.668262,9.155873,0.600000 +3.859649,9.410538,0.600000 +4.003190,9.656422,0.600000 +4.146730,9.941822,0.600000 From 6688d21428cb8ab4be981c86d2820c3e2b70c750 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Tue, 20 Jan 2026 17:25:30 -0500 Subject: [PATCH 12/50] Use more condensed validation data and improve validation figures --- .gitignore | 6 +- MITRotor/FlorisInterface/FlorisInterface.py | 64 +++---- MITRotor/FlorisInterface/IEA_15mw_rotor.csv | 51 ++++++ MITRotor/FlorisInterface/pitch_15mw.csv | 33 ---- .../FlorisInterface/pitch_tsr_ct_15mw.csv | 56 ------ MITRotor/FlorisInterface/tsr_15mw.csv | 33 ---- MITRotor/Momentum.py | 8 +- examples/example_05_floris_integration.py | 168 +++++++++++------- tests/test_floris_interface.py | 39 ++-- 9 files changed, 203 insertions(+), 255 deletions(-) create mode 100644 MITRotor/FlorisInterface/IEA_15mw_rotor.csv delete mode 100644 MITRotor/FlorisInterface/pitch_15mw.csv delete mode 100644 MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv delete mode 100644 MITRotor/FlorisInterface/tsr_15mw.csv diff --git a/.gitignore b/.gitignore index 646f286..272610c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,9 +14,9 @@ fig* *.whl # Allow these CSVs needed for the floris interface -!MITRotor/FlorisInterface/pitch_15mw.csv -!MITRotor/FlorisInterface/tsr_15mw.csv -!MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv +!MITRotor/FlorisInterface/IEA_15mw_rotor.csv + +Validation/ ### Python ### # Byte-compiled / optimized / DLL files diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 2ccdf26..0d96c5e 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -1,5 +1,6 @@ -import numpy as np import os +import numpy as np +import polars as pl from attrs import define, field from typing import Optional from scipy.interpolate import interp1d @@ -9,8 +10,9 @@ from floris.core.rotor_velocity import average_velocity, rotor_velocity_air_density_correction # MITRotor / UMM Imports from MITRotor.ReferenceTurbines import IEA15MW -from MITRotor.Momentum import UnifiedMomentum +from MITRotor.Momentum import MadsenMomentum from MITRotor.Geometry import BEMGeometry +from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw @@ -18,33 +20,32 @@ def default_bem_factory(): return BEM( rotor=IEA15MW(), - momentum_model=UnifiedMomentum(averaging="rotor"), + momentum_model=MadsenMomentum(averaging="annulus"), geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss() ) -# pitch vs windspeed curve if none provided by user +# pitch vs windspeed interpolater if none provided by user # for IEA 15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) -def default_pitch_csv(): +def default_pitch_interp(): module_dir = os.path.dirname(__file__) - return os.path.join(module_dir, "pitch_15mw.csv") - -# tsr vs windspeed curve if none provided by user + pitch_file = os.path.join(module_dir, "IEA_15mw_rotor.csv") + df = pl.read_csv(pitch_file) + wind_table = df["Wind [m/s]"].to_numpy() + pitch_table = df["Pitch [deg]"].to_numpy() + # TODO: should fill_value be extrapolate? + return interp1d(wind_table, pitch_table, kind="linear", fill_value="extrapolate", bounds_error=False) + +# tsr vs windspeed interpolater if none provided by user # for IEA 15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) -def default_tsr_csv(): +def default_tsr_interp(): module_dir = os.path.dirname(__file__) - return os.path.join(module_dir, "tsr_15mw.csv") - -def csv_to_interp(csv_file): - # read in csv - data = np.loadtxt(csv_file, delimiter=",", skiprows=1) - # split data into x (wind speed) and y (either pitch or tsr) - x = data[:, 0] - y = data[:, 1] - # sort by x (wind speed) - idx = np.argsort(x) - x = x[idx] - y = y[idx] - # return interpolator for y - return interp1d(x, y, kind="linear", fill_value="extrapolate", bounds_error=False) # TODO: should fill_value be extrapolate? + tsr_file = os.path.join(module_dir, "IEA_15mw_rotor.csv") + df = pl.read_csv(tsr_file) + wind_table = df["Wind [m/s]"].to_numpy() + tip_speed_table = df["Tip Speed [m/s]"].to_numpy() + tsr_table = tip_speed_table / wind_table + # TODO: should fill_value be extrapolate? + return interp1d(wind_table, tsr_table, kind="linear", fill_value="extrapolate", bounds_error=False) @define class MITRotorTurbine(BaseOperationModel): @@ -64,13 +65,9 @@ class MITRotorTurbine(BaseOperationModel): # user can define a BEM model if they want a different rotor, momentum model, or geometry bem_model = field(init = True, factory = default_bem_factory, type = BEM) - # user can define csv paths for pitch and tsr values - pitch_csv = field(init = True, factory = default_pitch_csv, type = str) - tsr_csv = field(init = True, factory = default_tsr_csv, type = str) - # create interp objects based on pitch and tsr csvs - _pitch_interp = field(init=False, default=None, type = interp1d, repr = False) - _tsr_interp = field(init=False, default=None, type = interp1d, repr = False) + pitch_interp = field(init=True, factory=default_pitch_interp, type = interp1d, repr = False) + tsr_interp = field(init=True, factory=default_tsr_interp, type = interp1d, repr = False) # save most recent solution by unique floris arguments _last_key = field(init=False, default=None, type = bytes) @@ -78,11 +75,6 @@ class MITRotorTurbine(BaseOperationModel): _Ct = field(init=False, default=None, type = NDArrayFloat) _power = field(init=False, default=None, type = NDArrayFloat) - def __attrs_post_init__(self): - # creates interpolation objects - self._pitch_interp = csv_to_interp(self.pitch_csv) - self._tsr_interp = csv_to_interp(self.tsr_csv) - def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_angles: np.ndarray) -> tuple: # saves key to uniquely identify farm state -> avoids re-solving for calls to power, thrust, and induction for same state return velocities.tobytes(), yaw_angles.tobytes(), tilt_angles.tobytes() @@ -124,8 +116,8 @@ def _update_solution(self, # get setpoints vel = rotor_average_velocities[findex, tindex] yaw, tilt = np.deg2rad(yaw_angles[findex, tindex]), np.deg2rad(tilt_angles[findex, tindex]) - pitch = np.deg2rad(self._pitch_interp(vel)) - tsr = self._tsr_interp(vel) + pitch = np.deg2rad(self.pitch_interp(vel)) + tsr = self.tsr_interp(vel) # solve BEM bem_sol = self.bem_model(pitch, tsr, yaw = yaw, tilt = tilt) # get induction and thrust coeff diff --git a/MITRotor/FlorisInterface/IEA_15mw_rotor.csv b/MITRotor/FlorisInterface/IEA_15mw_rotor.csv new file mode 100644 index 0000000..c5ce68c --- /dev/null +++ b/MITRotor/FlorisInterface/IEA_15mw_rotor.csv @@ -0,0 +1,51 @@ +Wind [m/s],Pitch [deg],Power [MW],Power Coefficient [-],Aero Power Coefficient [-],Rotor Speed [rpm],Tip Speed [m/s],Thrust [MN],Thrust Coefficient [-],Torque [MNm],Torque Coefficient [-],Blade Moment [MNm],Blade Moment Coefficient [-] +3,3.920293066,0.042500121,0.056434434,0.05897929,5,63.33974388,0.202909425,0.808309128,0.0848295,0.002806784,5.980185544,0.197868559 +3.54953237,3.913016973,0.292273273,0.234311418,0.244877465,5,63.33974388,0.275784048,0.784774049,0.583372359,0.01378822,7.854972515,0.185655162 +4.067900771,3.709535473,0.607683429,0.323656337,0.338251306,5,63.33974388,0.360568653,0.781205046,1.212925534,0.021827203,10.04565323,0.180776562 +4.553906848,3.347852063,0.980824467,0.372354525,0.389145491,5,63.33974388,0.454006762,0.784895445,1.957708542,0.028111524,12.46569389,0.178999911 +5.006427063,2.905271743,1.401604341,0.400460354,0.418518725,5,63.33974388,0.550743112,0.787791082,2.797577836,0.033237705,14.97412576,0.177905892 +5.424415288,2.410742282,1.858097567,0.41737602,0.436197187,5,63.33974388,0.648091847,0.789675144,3.708730359,0.03753393,17.50236286,0.177131362 +5.806905228,1.897891096,2.33681832,0.42786672,0.447160954,5,63.33974388,0.743097627,0.790085645,4.66424864,0.041190481,19.97338486,0.176387107 +6.153012649,1.38709008,2.823250666,0.434514015,0.454108003,5,63.33974388,0.833653636,0.789455775,5.635159124,0.044323619,22.33283369,0.175659992 +6.461937428,0.891713024,3.302257138,0.438773526,0.458559593,5,63.33974388,0.918175231,0.78834778,6.591247694,0.047005295,24.54016065,0.175007454 +6.732965398,0.425207394,3.758708724,0.441506699,0.461416015,5,63.33974388,0.995161603,0.787043287,7.502317104,0.049281883,26.55670159,0.174448007 +6.965470002,0.000469162,4.17814357,0.443251132,0.463239112,5,63.33974388,1.063280746,0.785714686,8.339501745,0.05118514,28.34690587,0.173984056 +7.158913742,0,4.546959581,0.444321653,0.46363055,5.086081797,64.43022368,1.11334287,0.778847528,8.908071675,0.051759978,29.65857718,0.172329924 +7.312849418,0,4.855095716,0.445098035,0.46363055,5.195446076,65.81564476,1.161737302,0.778847528,9.295284892,0.051759978,30.94776674,0.172329924 +7.426921164,0,5.091278414,0.445572294,0.46363055,5.27648885,66.84229047,1.198263417,0.778847528,9.587537406,0.051759978,31.92079369,0.172329924 +7.500865272,0,5.248186603,0.445854287,0.46363055,5.329022767,67.50778745,1.22224256,0.778847528,9.779399169,0.051759978,32.55957918,0.172329924 +7.534510799,0,5.320523056,0.445971313,0.46363055,5.35292638,67.81059719,1.233232019,0.778847528,9.867327955,0.051759978,32.8523297,0.172329924 +7.541241633,0,5.335074621,0.445994704,0.46363055,5.357708331,67.8711747,1.23543638,0.778847528,9.884965469,0.051759978,32.91105213,0.172329924 +7.58833327,0,5.437629628,0.44615751,0.46363055,5.391164791,68.29499943,1.250914035,0.778847528,10.00880519,0.051759978,33.32336468,0.172329924 +7.675676842,0,5.630967375,0.446427293,0.46363055,5.453218417,69.08109158,1.279876417,0.778847528,10.2405388,0.051759978,34.09489971,0.172329924 +7.803070431,0,5.920680499,0.446779068,0.46363055,5.543725753,70.22763388,1.322713319,0.778847528,10.58328514,0.051759978,35.23604104,0.172329924 +7.970219531,0,6.314795749,0.44716338,0.46363055,5.662477568,71.73197578,1.379987779,0.778847528,11.04154918,0.051759978,36.76178755,0.172329924 +8.176737731,0,6.824124693,0.447532442,0.46363055,5.809199332,73.59063957,1.452428655,0.778847528,11.62116264,0.051759978,38.69155545,0.172329924 +8.422147605,0,7.462468983,0.447849163,0.46363055,5.983551858,75.79932844,1.540920985,0.778847528,12.3292069,0.051759978,41.04892142,0.172329924 +8.70588182,0,8.237943086,0.447608431,0.46363055,6.185132081,78.35293638,1.646494209,0.778847528,13.17391868,0.051759978,43.86130896,0.172329924 +9.027284445,0,9.167503057,0.446783839,0.46363055,6.413473991,81.24556,1.770308387,0.778847528,14.16457987,0.051759978,47.15962114,0.172329924 +9.385612468,0,10.28468981,0.445985887,0.46363055,6.668049714,84.47051221,1.913638541,0.778847528,15.31139216,0.051759978,50.97782356,0.172329924 +9.780037514,0,11.61664761,0.44522242,0.46363055,6.948270725,88.02033763,2.077857279,0.778847528,16.62533805,0.051759978,55.3524814,0.172329924 +10.20964776,0,13.19374497,0.444481389,0.46363055,7.253489215,91.88682983,2.264415873,0.778847528,18.11802945,0.051759978,60.3222554,0.172329924 +10.65843263,0,15,0.444149321,0.463833394,7.499240933,95,2.447339849,0.772369945,19.94703495,0.05228731,65.14869599,0.170774759 +10.67345004,0.511974392,15.00000265,0.442277294,0.461878402,7.499240933,95,2.374311052,0.74721528,19.9470383,0.052140287,63.06741054,0.164854194 +11.17037214,3.723733263,14.99997215,0.385838268,0.402938078,7.499240933,95,1.956901748,0.562278542,19.94699774,0.047604378,50.90543244,0.12148803 +11.6992653,5.396486368,15.00000888,0.33584085,0.350724844,7.499240933,95,1.769139016,0.463406962,19.94704659,0.043397635,45.21424327,0.098370013 +12.25890683,6.766694447,15.00000059,0.291913256,0.304850441,7.499240933,95,1.630599159,0.389010657,19.94703557,0.039525695,40.89463241,0.081034035 +12.84800295,7.989590009,15.0000001,0.2535725,0.264810476,7.499240933,95,1.518234459,0.329750424,19.94703492,0.03598419,37.29572857,0.067281007 +13.46519181,9.124292675,14.99994632,0.220277351,0.230039733,7.499240933,95,1.423067352,0.281396143,19.9469634,0.032760939,34.16497221,0.05611263 +14.10904661,10.20005088,15.00008104,0.191477776,0.199963801,7.499240933,95,1.340503102,0.241429458,19.94714255,0.029839394,31.37410139,0.046933247 +14.77807889,11.23370987,15.00005146,0.166631299,0.174016164,7.499240933,95,1.267744754,0.208119912,19.94710322,0.027198723,28.84591141,0.039332626 +15.470742,12.23548853,15.00003481,0.145236779,0.151673469,7.499240933,95,1.20299036,0.180201181,19.94708107,0.02481771,26.53102258,0.033009302 +16.18543466,13.21207233,15.00002476,0.12683428,0.132455397,7.499240933,95,1.144953313,0.156695606,19.94706771,0.022674357,24.39444366,0.027729806 +16.92050464,14.16785471,15.00001806,0.111011922,0.115931814,7.499240933,95,1.092675034,0.136830266,19.9470588,0.020747076,22.41059375,0.023309415 +17.67425264,15.10569973,15.00001315,0.097406118,0.101723021,7.499240933,95,1.045410488,0.119983771,19.94705227,0.019015215,20.56016302,0.019599684 +18.44493615,16.02744622,15.00000923,0.08569941,0.089497487,7.499240933,95,1.002561347,0.105651196,19.94704705,0.017459385,18.82803369,0.016479927 +19.23077353,16.93422766,15.000006,0.075616913,0.078968149,7.499240933,95,0.963634907,0.093419339,19.94704276,0.016061631,17.20197892,0.013851268 +20.02994808,17.82668205,15.00000341,0.066922115,0.069888009,7.499240933,95,0.928217511,0.082948375,19.94703931,0.014805512,15.6718209,0.011632269 +20.8406123,18.70508213,15.00000149,0.059412476,0.062045553,7.499240933,95,0.895956018,0.07395772,19.94703676,0.013676094,14.22892793,0.009755642 +21.66089211,19.56943768,15.00000033,0.052915149,0.055260274,7.499240933,95,0.866544894,0.066214966,19.94703522,0.012659901,12.8658372,0.008165636 +22.4888912,20.41950905,15.00018216,0.047283561,0.049379102,7.499240933,95,0.839725354,0.059527679,19.94727702,0.011744977,11.57634071,0.006816161 +23.32269542,21.25504455,15.00000054,0.042390918,0.044269624,7.499240933,95,0.815233262,0.053733135,19.9470355,0.010920072,10.35411323,0.005668395 +24.1603772,22.07544699,15.00000177,0.038132735,0.039822724,7.499240933,95,0.79288419,0.048699008,19.94703713,0.010175965,9.195130033,0.004690888 +25,22.88018135,15.0000035,0.034418276,0.035943645,7.499240933,95,0.772480289,0.044312389,19.94703943,0.009503927,8.095078123,0.003856965 \ No newline at end of file diff --git a/MITRotor/FlorisInterface/pitch_15mw.csv b/MITRotor/FlorisInterface/pitch_15mw.csv deleted file mode 100644 index ad33a54..0000000 --- a/MITRotor/FlorisInterface/pitch_15mw.csv +++ /dev/null @@ -1,33 +0,0 @@ -wind_speed, pitch -2.9492833517089307, 3.876651982378855 -3.2800441014332966, 3.876651982378855 -3.6990077177508267, 3.876651982378855 -4.117971334068358, 3.436123348017621 -4.911797133406836, 2.8193832599118944 -5.507166482910694, 2.026431718061674 -6.080485115766262, 1.3215859030837005 -6.896361631753032, 0.0881057268722467 -7.844542447629548, 0 -8.7045203969129, 0 -9.432194046306504, 0 -10.115766262403529, 1.8502202643171808 -10.77728776185226, 3.1718061674008813 -11.1742006615215, 3.6123348017621146 -11.637265711135612, 4.845814977973569 -12.078280044101433, 5.991189427312776 -12.717750826901874, 7.48898678414097 -13.864388092613009, 9.60352422907489 -14.547960308710033, 10.748898678414097 -15.231532524807056, 11.718061674008812 -16.245865490628447, 13.215859030837006 -17.039691289966925, 14.273127753303966 -17.723263506063944, 15.154185022026432 -18.362734288864388, 15.947136563876652 -19.04630650496141, 16.740088105726873 -19.906284454244762, 17.709251101321588 -20.45755237045204, 18.325991189427313 -21.604189636163174, 19.559471365638768 -22.640573318632853, 20.61674008810573 -23.721058434399115, 21.762114537444933 -24.40463065049614, 22.46696035242291 -25.02205071664829, 22.995594713656388 \ No newline at end of file diff --git a/MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv b/MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv deleted file mode 100644 index 47c23f4..0000000 --- a/MITRotor/FlorisInterface/pitch_tsr_ct_15mw.csv +++ /dev/null @@ -1,56 +0,0 @@ -pitch,tsr,Ct --4.952153,7.140505,0.750000 --4.529506,7.166850,0.750000 --4.130781,7.210757,0.750000 --3.740032,7.254665,0.750000 --3.325359,7.316136,0.750000 --3.038278,7.364435,0.750000 --2.655502,7.443469,0.750000 --2.185008,7.553238,0.750000 --1.866029,7.645445,0.750000 --1.491228,7.759605,0.750000 --1.180223,7.878156,0.750000 --0.837321,8.014270,0.750000 --0.454545,8.194292,0.750000 --0.119617,8.365532,0.750000 -0.199362,8.545554,0.750000 -0.486443,8.729967,0.750000 -0.757576,8.927552,0.750000 -0.996810,9.111965,0.750000 -1.299841,9.371021,0.750000 -1.531100,9.586169,0.750000 -1.858054,9.924259,0.750000 --4.904306,8.163557,0.900000 --4.577352,8.225027,0.900000 --4.242424,8.321625,0.900000 --3.827751,8.444566,0.900000 --3.460925,8.567508,0.900000 --3.133971,8.699232,0.900000 --2.759171,8.857300,0.900000 --2.448166,8.997805,0.900000 --2.105263,9.173436,0.900000 --1.778309,9.353458,0.900000 --1.395534,9.572997,0.900000 --1.076555,9.788145,0.900000 --0.781499,10.007684,0.900000 --4.920255,9.353458,1.050000 --4.649123,9.454446,1.050000 --4.330144,9.599341,1.050000 --4.082935,9.717892,1.050000 --3.819777,9.845225,1.050000 --3.548644,9.994512,1.050000 --3.261563,10.152580,1.050000 -0.805423,7.030735,0.600000 -1.156300,7.171240,0.600000 -1.555024,7.355653,0.600000 -1.913876,7.548847,0.600000 -2.232855,7.742042,0.600000 -2.511962,7.952799,0.600000 -2.799043,8.194292,0.600000 -3.046252,8.418222,0.600000 -3.269537,8.655324,0.600000 -3.484848,8.892426,0.600000 -3.668262,9.155873,0.600000 -3.859649,9.410538,0.600000 -4.003190,9.656422,0.600000 -4.146730,9.941822,0.600000 diff --git a/MITRotor/FlorisInterface/tsr_15mw.csv b/MITRotor/FlorisInterface/tsr_15mw.csv deleted file mode 100644 index 096640a..0000000 --- a/MITRotor/FlorisInterface/tsr_15mw.csv +++ /dev/null @@ -1,33 +0,0 @@ -wind_speed, tsr -2.993384785005513, 20.792951541850222 -3.2138919514884234, 19.383259911894275 -3.478500551267916, 18.061674008810574 -3.7210584343991178, 16.82819383259912 -4.007717750826902, 15.418502202643174 -4.294377067254686, 14.537444933920705 -4.603087100330761, 13.480176211453745 -4.955898566703418, 12.687224669603525 -5.352811466372657, 11.629955947136564 -5.83792723263506, 10.572687224669604 -6.2348401323043, 9.955947136563877 -6.65380374862183, 9.33920704845815 -7.006615214994487, 8.986784140969164 -7.9547960308710035, 8.986784140969164 -8.880926130099228, 8.81057268722467 -9.807056229327454, 8.986784140969164 -10.689084895259096, 8.986784140969164 -11.681367144432194, 8.370044052863436 -13.114663726571113, 7.312775330396476 -14.283351708930539, 6.607929515418503 -15.143329658213892, 6.255506607929516 -16.245865490628447, 5.814977973568282 -16.863285556780596, 5.638766519823789 -17.67916207276736, 5.462555066079296 -18.80374862183021, 5.110132158590309 -19.928335170893053, 4.845814977973569 -20.87651598676957, 4.581497797356828 -21.49393605292172, 4.493392070484582 -22.39801543550165, 4.229074889867841 -23.16979051819184, 4.052863436123348 -23.96361631753032, 3.9647577092511015 -24.933847850055127, 3.788546255506608 \ No newline at end of file diff --git a/MITRotor/Momentum.py b/MITRotor/Momentum.py index 7f1dd1a..7a3c99c 100644 --- a/MITRotor/Momentum.py +++ b/MITRotor/Momentum.py @@ -269,8 +269,8 @@ def __init__(self, def compute_induction(self, Cx: ArrayLike, yaw: float, tilt: float = 0.0) -> ArrayLike: - if tilt != 0: - raise ValueError("Tilt not supported by the Madsen momentum model. Use UMM.") + # if tilt != 0: + # raise ValueError("Tilt not supported by the Madsen momentum model. Use UMM.") if self.cosine_exponent: Ct = Cx / (np.cos(yaw)**2) else: @@ -280,8 +280,8 @@ def compute_induction(self, Cx: ArrayLike, yaw: float, tilt: float = 0.0) -> Arr return an def compute_initial_wake_velocities(self, Ct: float, yaw: float, tilt: float = 0.0) -> ArrayLike: - if tilt != 0: - raise ValueError("Tilt not supported by the Madsen momentum model. Use UMM.") + # if tilt != 0: + # raise ValueError("Tilt not supported by the Madsen momentum model. Use UMM.") u4 = np.sqrt(1 - Ct) v4 = - (1/4) * Ct * np.sin(yaw) w4 = 0.0 diff --git a/examples/example_05_floris_integration.py b/examples/example_05_floris_integration.py index fd8aeb2..8a5b401 100644 --- a/examples/example_05_floris_integration.py +++ b/examples/example_05_floris_integration.py @@ -1,13 +1,18 @@ -import numpy as np import os +import numpy as np +import polars as pl from pathlib import Path + import matplotlib.pyplot as plt from matplotlib import cm from matplotlib.colors import Normalize from matplotlib.cm import ScalarMappable + from floris import FlorisModel, TimeSeries -from MITRotor.FlorisInterface.FlorisInterface import csv_to_interp, default_bem_factory, MITRotorTurbine +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp +figdir = Path("fig") +floris_air_density = 1.225 # ------------------ run basic case -------------------------------------------------------- fmodel = FlorisModel("defaults") time_series = TimeSeries( @@ -34,110 +39,137 @@ print("Axial induction factors [-]:\n", fmodel.get_turbine_axial_induction_factors(), "\n") # -------------------- plot pitch and tsr control curves, as well as CT for IEA15MW ------------------ +# Credit to Ilan Upfal for initial validation of MITRotor vs IEA15MW and much of the script below. +# Floris Interface written and tested by Skylar Gering. module_dir = os.path.dirname(__file__) # examples/ -csv_dir = os.path.join(module_dir, "..", "MITRotor", "FlorisInterface") +csv_file = os.path.join(module_dir, "..", "MITRotor", "FlorisInterface", "IEA_15mw_rotor.csv") +df = pl.read_csv(csv_file) -wind_speeds = np.linspace(5, 25.0, 20) +wind_table = df["Wind [m/s]"].to_numpy() +wind_speeds = np.linspace(3, 25, 50) wind_dirs = np.full_like(wind_speeds, 270.0) turbulence_intensity = np.zeros_like(wind_speeds) -# plot pitch and tsr control curves for IEA15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) -pitch_csv = os.path.join(csv_dir, "pitch_15mw.csv") -tsr_csv = os.path.join(csv_dir, "tsr_15mw.csv") -pitch_interp = csv_to_interp(pitch_csv) -tsr_interp = csv_to_interp(tsr_csv) +# ------- plot pitch and tsr control curves for IEA15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) -------- +pitch_interp = default_pitch_interp() +tsr_interp = default_tsr_interp() +tsrs = [tsr_interp(u) for u in wind_speeds] +pitches = [pitch_interp(u) for u in wind_speeds] # plot interpolated pitch and tsr data fig, ax = plt.subplots(figsize=(8, 6)) ax.scatter( wind_speeds, - pitch_interp(wind_speeds), + pitches, s=40, edgecolors="k", label = "Interpolated Pitch [deg]" ) ax.scatter( wind_speeds, - tsr_interp(wind_speeds), + tsrs, s=40, edgecolors="k", label = "Interpolated Tip-Speed Ratio [-]" ) - # load and plot raw CSV data -tsr_data = np.loadtxt(tsr_csv, delimiter=",", skiprows=1) -pitch_data = np.loadtxt(pitch_csv, delimiter=",", skiprows=1) -tsr_ws, tsr_vals = tsr_data[:, 0], tsr_data[:, 1] -pitch_ws, pitch_vals = pitch_data[:, 0], pitch_data[:, 1] ax.plot( - pitch_ws, - pitch_vals, + wind_table, + df["Pitch [deg]"].to_numpy(), label = "Pitch [deg]" ) ax.plot( - tsr_ws, - tsr_vals, + wind_table, + df["Tip Speed [m/s]"].to_numpy() / wind_table, label = "Tip-Speed Ratio [-]" ) -ax.set_xlabel("Wind Speed [m/s]") -ax.set_title("IEA 15MW: Fixed Bottom Trajectories") -plt.legend() - -# compute CT from floris +ax.set_title("IEA 15MW: Fixed Bottom Trajectories", size = 18) +ax.set_xlabel("Wind Speed [m/s]", size = 16) +ax.tick_params(labelsize=14) +ax.legend(fontsize = 14) +plt.savefig(figdir / "example_5_pitch_tsr_interpolation.png", dpi=300) + +# -------- plot CT and CP values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) ------- +# solve Madsen Momentum Model though MITRotor +bem = default_bem_factory() +mit_sols = [bem(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] +mit_Ct = [sol.Ct() for sol in mit_sols] +mit_Cp = [sol.Cp() for sol in mit_sols] + +# solve FLORIS with MITRotor fmodel = FlorisModel("defaults") - time_series = TimeSeries( wind_speeds=wind_speeds, wind_directions=wind_dirs, turbulence_intensities=turbulence_intensity, ) - fmodel.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) fmodel.set_operation_model(MITRotorTurbine()) fmodel.run() floris_Ct = fmodel.get_turbine_thrust_coefficients() +rotor_area = np.pi * bem.rotor.R**2 +floris_power = np.squeeze(fmodel.get_turbine_powers()) +floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +# plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) fig, ax = plt.subplots(figsize=(8, 6)) -cmap = cm.viridis - -# plot setpoint curves for IEA15MW from figure 3.2 (https://docs.nrel.gov/docs/fy20osti/75698.pdf) -setpoint_curves = os.path.join(csv_dir, "pitch_tsr_ct_15mw.csv") -data = np.loadtxt(setpoint_curves, delimiter=",", skiprows=1) -all_cts = np.concatenate([data[:, 2], floris_Ct.flatten()]) -norm = Normalize(vmin=all_cts.min(), vmax=all_cts.max()) - -for ct in np.unique(data[:, 2]): - mask = data[:, 2] == ct - ax.plot( - data[mask, 0], - data[mask, 1], - color=cmap(norm(ct)), - linewidth=2, - label=f"Ct ≈ {ct:.3f}", - ) - -# plot FLORIS points -sc = ax.scatter( - pitch_interp(wind_speeds), - tsr_interp(wind_speeds), - c=floris_Ct, - cmap=cmap, - norm=norm, - s=40, - edgecolors="k", - label = "FLORIS with MITRotor" +ax.plot( + wind_table, + df["Thrust Coefficient [-]"].to_list(), + linewidth=2, + label="IEA15MW $C_T$", + color='tab:orange', + linestyle = "solid" +) + +ax.plot( + wind_speeds, + mit_Ct, + label="MITRotor $C_T$", + linewidth=2, + color='tab:orange', + linestyle = "dashed" +) +ax.plot( + wind_speeds, + floris_Ct, + label="FLORIS $C_T$", + linewidth=2, + color='darkorange', + linestyle = "dotted" +) + +ax.set_xlabel("Wind Speed [m/s]") + + +# plot Cp values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) +ax.plot( + wind_table, + df["Aero Power Coefficient [-]"].to_list(), + label="IEA15MW $C_P$", + linewidth=2, + color='tab:blue', + linestyle = "solid" +) +ax.plot( + wind_speeds, + mit_Cp, + label="MITRotor $C_P$", + linewidth=2, + color='tab:blue', + linestyle = "dashed" +) +ax.plot( + wind_speeds, + floris_Cp, + label="FLORIS $C_P$", + linewidth=2, + color='tab:blue', + linestyle = "dotted" ) +ax.set_title("IEA 15 MW FLORIS Interface Validation", size = 18) +ax.set_xlabel("Wind Speed [m/s]", size = 16) +ax.tick_params(labelsize=14) +ax.legend(fontsize = 14) +plt.savefig(figdir / "example_5_IEA15mw_CT_CP.png", dpi=300) -# colorbar that covers all Ct values -sm = ScalarMappable(norm=norm, cmap=cmap) -sm.set_array([]) -plt.colorbar(sm, ax=ax, label="$C_T$") - -# label plot -ax.set_xlabel("Pitch [deg]") -ax.set_ylabel("Tip-Speed Ratio [-]") -ax.set_title("IEA 15MW: $C_T$ Control Curves vs FLORIS/MITRotor") -ax.grid(True, alpha=0.3) -ax.legend(fontsize=9) -plt.tight_layout() -plt.show() diff --git a/tests/test_floris_interface.py b/tests/test_floris_interface.py index 46f0fe8..ad109ad 100644 --- a/tests/test_floris_interface.py +++ b/tests/test_floris_interface.py @@ -1,34 +1,29 @@ +import os import numpy as np import pytest -import os +import polars as pl from numpy.testing import assert_almost_equal, assert_allclose from floris import FlorisModel, TimeSeries -from MITRotor.FlorisInterface import FlorisInterface -from MITRotor.FlorisInterface.FlorisInterface import default_bem_factory, default_pitch_csv, default_tsr_csv -from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, csv_to_interp +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp def test_pitch_tsr_interpolation(): - # get 15MW CSV file paths - module_dir = os.path.dirname(__file__) # tests/ - pitch_csv = os.path.join(module_dir, "..", "MITRotor", "FlorisInterface", "pitch_15mw.csv") - tsr_csv = os.path.join(module_dir, "..", "MITRotor", "FlorisInterface", "tsr_15mw.csv") - pitch_csv = os.path.abspath(pitch_csv) - tsr_csv = os.path.abspath(tsr_csv) - - # create interpolators - tsr_interp = csv_to_interp(tsr_csv) - pitch_interp = csv_to_interp(pitch_csv) + # create default interpolators + tsr_interp = default_tsr_interp() + pitch_interp = default_pitch_interp() # load raw CSV data - tsr_data = np.loadtxt(tsr_csv, delimiter=",", skiprows=1) - pitch_data = np.loadtxt(pitch_csv, delimiter=",", skiprows=1) - tsr_ws, tsr_vals = tsr_data[:, 0], tsr_data[:, 1] - pitch_ws, pitch_vals = pitch_data[:, 0], pitch_data[:, 1] + module_dir = os.path.dirname(__file__) # tests/ + validation_csv = os.path.abspath(os.path.join(module_dir, "..", "MITRotor", "FlorisInterface", "IEA_15mw_rotor.csv")) + df = pl.read_csv(validation_csv) + wind_data = df["Wind [m/s]"].to_numpy() + pitch_data = df["Pitch [deg]"].to_numpy() + tip_speed_data = df["Tip Speed [m/s]"].to_numpy() + tsr_data = tip_speed_data / wind_data # interpolator reproduces raw data - assert_allclose(tsr_interp(tsr_ws), tsr_vals, rtol=1e-12, atol=1e-12) - assert_allclose(pitch_interp(pitch_ws), pitch_vals, rtol=1e-12, atol=1e-12) + assert_allclose(tsr_interp(wind_data), tsr_data, rtol=1e-12, atol=1e-12) + assert_allclose(pitch_interp(wind_data), pitch_data, rtol=1e-12, atol=1e-12) # reasonable values x_interp_vals = np.linspace(0.0, 25.0, 100) @@ -44,8 +39,8 @@ def test_pitch_tsr_interpolation(): # compute MITRotor BEM outputs directly def compute_mitrotor_cp_ct_a(wind_speeds, yaw_deg = 0.0, tilt_deg = 0.0): bem_model = default_bem_factory() # default BEM (IEA15MW) used in floris interface - pitch_interp = csv_to_interp(default_pitch_csv()) # IEA15MW pitch curve - tsr_interp = csv_to_interp(default_tsr_csv()) # IEA15MW tsr curve + pitch_interp = default_pitch_interp() # IEA15MW pitch curve + tsr_interp = default_tsr_interp() # IEA15MW tsr curve n = len(wind_speeds) Ct = np.empty(n) From a5798d4a7574d6d4c684c28e50d94137e82704b1 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 21 Jan 2026 13:59:17 -0500 Subject: [PATCH 13/50] Switch default to UMM Rotor-averaged and add more rotors to example for testing --- MITRotor/FlorisInterface/FlorisInterface.py | 7 +- examples/example_05_floris_integration.py | 325 ++++++++++++++++---- 2 files changed, 276 insertions(+), 56 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 0d96c5e..f496c69 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -7,20 +7,19 @@ # FLORIS Imports from floris.type_dec import floris_float_type, NDArrayFloat from floris.core.turbine.operation_models import BaseOperationModel -from floris.core.rotor_velocity import average_velocity, rotor_velocity_air_density_correction +from floris.core.rotor_velocity import average_velocity # MITRotor / UMM Imports from MITRotor.ReferenceTurbines import IEA15MW -from MITRotor.Momentum import MadsenMomentum +from MITRotor.Momentum import UnifiedMomentum from MITRotor.Geometry import BEMGeometry from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM -from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw # default rotor if none provided by user (IEA 15MW) def default_bem_factory(): return BEM( rotor=IEA15MW(), - momentum_model=MadsenMomentum(averaging="annulus"), + momentum_model=UnifiedMomentum(averaging="rotor"), geometry=BEMGeometry(Nr=10, Ntheta=20), tiploss_model=NoTipLoss() ) diff --git a/examples/example_05_floris_integration.py b/examples/example_05_floris_integration.py index 8a5b401..f4baae4 100644 --- a/examples/example_05_floris_integration.py +++ b/examples/example_05_floris_integration.py @@ -2,14 +2,27 @@ import numpy as np import polars as pl from pathlib import Path +import time +import warnings + +warnings.filterwarnings("ignore", category=RuntimeWarning) # JUST FOR NOW + import matplotlib.pyplot as plt from matplotlib import cm from matplotlib.colors import Normalize from matplotlib.cm import ScalarMappable +# Floris imports from floris import FlorisModel, TimeSeries + +# MITRotor / UMM Imports from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp +from MITRotor.ReferenceTurbines import IEA15MW +from MITRotor.Momentum import UnifiedMomentum, MadsenMomentum +from MITRotor.Geometry import BEMGeometry +from MITRotor.TipLoss import NoTipLoss +from MITRotor.BEMSolver import BEM figdir = Path("fig") floris_air_density = 1.225 @@ -90,86 +103,294 @@ plt.savefig(figdir / "example_5_pitch_tsr_interpolation.png", dpi=300) # -------- plot CT and CP values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) ------- -# solve Madsen Momentum Model though MITRotor -bem = default_bem_factory() -mit_sols = [bem(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] -mit_Ct = [sol.Ct() for sol in mit_sols] -mit_Cp = [sol.Cp() for sol in mit_sols] +# solve UMM-BEM though MITRotor - rotor averaged +bem_rotor_umm = default_bem_factory() +mit_rotor_umm_start = time.time() +mit_sols_rotor_umm = [bem_rotor_umm(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] +mit_rotor_umm_end = time.time() +mit_Ct_rotor_umm = [sol.Ct() for sol in mit_sols_rotor_umm] +mit_Cp_rotor_umm = [sol.Cp() for sol in mit_sols_rotor_umm] +print("MITRotor UMM-BEM Rotor-Averaged: " + str(mit_rotor_umm_end - mit_rotor_umm_start) + " seconds") -# solve FLORIS with MITRotor -fmodel = FlorisModel("defaults") +# solve UMM-BEM though MITRotor - annulus averaged +bem_annulus_umm = BEM( + rotor=IEA15MW(), + momentum_model=UnifiedMomentum(averaging="annulus"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss(), + ) +mit_annulus_umm_start = time.time() +mit_sols_annulus_umm = [bem_annulus_umm(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] +mit_annulus_umm_end = time.time() +mit_Ct_annulus_umm = [sol.Ct() for sol in mit_sols_annulus_umm] +mit_Cp_annulus_umm = [sol.Cp() for sol in mit_sols_annulus_umm] +print("MITRotor UMM-BEM Annulus-Averaged: " + str(mit_annulus_umm_end - mit_annulus_umm_start) + " seconds") + +# solve Madsen-BEM though MITRotor - rotor averaged +bem_rotor_madesen = BEM( + rotor=IEA15MW(), + momentum_model=MadsenMomentum(averaging="rotor"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss() + ) +mit_rotor_madsen_start = time.time() +mit_sols_rotor_madsen = [bem_rotor_madesen(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] +mit_rotor_madsen_end = time.time() +mit_Ct_rotor_madsen = [sol.Ct() for sol in mit_sols_rotor_madsen] +mit_Cp_rotor_madsen = [sol.Cp() for sol in mit_sols_rotor_madsen] +print("MITRotor Madsen-BEM Rotor-Averaged: " + str(mit_rotor_madsen_end - mit_rotor_madsen_start) + " seconds") + +# solve Madsen-BEM though MITRotor - annulus averaged +bem_annulus_madesen = BEM( + rotor=IEA15MW(), + momentum_model=MadsenMomentum(averaging="annulus"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss() + ) +mit_annulus_madsen_start = time.time() +mit_sols_annulus_madsen = [bem_annulus_madesen(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] +mit_annulus_madsen_end = time.time() +mit_Ct_annulus_madsen = [sol.Ct() for sol in mit_sols_annulus_madsen] +mit_Cp_annulus_madsen = [sol.Cp() for sol in mit_sols_annulus_madsen] +print("MITRotor Madsen-BEM Annulus-Averaged: " + str(mit_annulus_madsen_end - mit_annulus_madsen_start) + " seconds") + +# solve FLORIS with UMM-BEM though MITRotor - rotor averaged time_series = TimeSeries( wind_speeds=wind_speeds, wind_directions=wind_dirs, turbulence_intensities=turbulence_intensity, ) -fmodel.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) -fmodel.set_operation_model(MITRotorTurbine()) -fmodel.run() -floris_Ct = fmodel.get_turbine_thrust_coefficients() -rotor_area = np.pi * bem.rotor.R**2 -floris_power = np.squeeze(fmodel.get_turbine_powers()) -floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +fmodel_rotor_umm = FlorisModel("defaults") +fmodel_rotor_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) +fmodel_rotor_umm.set_operation_model(MITRotorTurbine()) # default bem_model uses rotor-averaging +floris_rotor_umm_start = time.time() +fmodel_rotor_umm.run() +floris_rotor_umm_end = time.time() +floris_Ct_rotor_umm = fmodel_rotor_umm.get_turbine_thrust_coefficients() +rotor_area = np.pi * bem_rotor_umm.rotor.R**2 +floris_power_rotor_umm = np.squeeze(fmodel_rotor_umm.get_turbine_powers()) +floris_Cp_rotor_umm = floris_power_rotor_umm / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +print("FLORIS UMM-BEM Rotor-Averaged: " + str(floris_rotor_umm_end - floris_rotor_umm_start) + " seconds") + +# solve FLORIS with UMM-BEM though MITRotor - annulus averaged +fmodel_annulus_umm = FlorisModel("defaults") +fmodel_annulus_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) +fmodel_annulus_umm.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_umm)) # default bem_model uses rotor-averaging +floris_annulus_umm_start = time.time() +fmodel_annulus_umm.run() +floris_annulus_umm_end = time.time() +floris_Ct_annulus_umm = fmodel_annulus_umm.get_turbine_thrust_coefficients() +floris_power_annulus_umm = np.squeeze(fmodel_annulus_umm.get_turbine_powers()) +floris_Cp_annulus_umm = floris_power_annulus_umm / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +print("FLORIS UMM-BEM Annulus-Averaged: " + str(floris_annulus_umm_end - floris_annulus_umm_start) + " seconds") + +# solve FLORIS with Madsen-BEM though MITRotor - rotor averaged +fmodel_rotor_madsen = FlorisModel("defaults") +fmodel_rotor_madsen.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) +fmodel_rotor_madsen.set_operation_model(MITRotorTurbine(bem_model = bem_rotor_madesen)) # default bem_model uses rotor-averaging +floris_rotor_madsen_start = time.time() +fmodel_rotor_madsen.run() +floris_rotor_madsen_end = time.time() +floris_Ct_rotor_madsen = fmodel_rotor_madsen.get_turbine_thrust_coefficients() +floris_power_rotor_madsen = np.squeeze(fmodel_rotor_madsen.get_turbine_powers()) +floris_Cp_rotor_madsen = floris_power_rotor_madsen / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +print("FLORIS Madsen-BEM Rotor-Averaged: " + str(floris_rotor_madsen_end - floris_rotor_madsen_start) + " seconds") + +# solve FLORIS with Madsen-BEM though MITRotor - annulus averaged +fmodel_annulus_madsen = FlorisModel("defaults") +fmodel_annulus_madsen.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) +fmodel_annulus_madsen.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_madesen)) # default bem_model uses rotor-averaging +floris_annulus_madsen_start = time.time() +fmodel_annulus_madsen.run() +floris_annulus_madsen_end = time.time() +floris_Ct_annulus_madsen = fmodel_annulus_madsen.get_turbine_thrust_coefficients() +floris_power_annulus_madsen = np.squeeze(fmodel_annulus_madsen.get_turbine_powers()) +floris_Cp_annulus_madsen = floris_power_annulus_madsen / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +print("FLORIS Madsen-BEM Annulus-Averaged: " + str(floris_annulus_madsen_end - floris_annulus_madsen_start) + " seconds") # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) -fig, ax = plt.subplots(figsize=(8, 6)) -ax.plot( +fig, (ax0, ax1) = plt.subplots(figsize=(16, 8), ncols = 2, sharex = True, sharey = True) +fig.suptitle("IEA 15 MW FLORIS Interface Validation", size = 18) +alpha = 0.8 +ax0.plot( wind_table, df["Thrust Coefficient [-]"].to_list(), - linewidth=2, - label="IEA15MW $C_T$", + linewidth=4, + label="IEA15MW", color='tab:orange', - linestyle = "solid" + linestyle = "solid", + alpha = alpha, ) -ax.plot( +ax0.plot( wind_speeds, - mit_Ct, - label="MITRotor $C_T$", - linewidth=2, - color='tab:orange', - linestyle = "dashed" + mit_Ct_rotor_umm, + label="MITRotor UMM Rotor-Averaged", + linewidth=4, + color='tab:blue', + linestyle = "solid", + alpha = alpha, ) -ax.plot( +ax0.plot( wind_speeds, - floris_Ct, - label="FLORIS $C_T$", - linewidth=2, - color='darkorange', - linestyle = "dotted" + mit_Ct_annulus_umm, + label="MITRotor UMM Annulus-Averaged", + linewidth=4, + color='tab:green', + linestyle = "solid", + alpha = alpha, +) +# ax0.plot( +# wind_speeds, +# mit_Ct_rotor_madsen, +# label="MITRotor Madsen Rotor-Averaged", +# linewidth=4, +# color='tab:purple', +# linestyle = "solid", +# alpha = alpha, +# ) +# ax0.plot( +# wind_speeds, +# mit_Ct_annulus_madsen, +# label="MITRotor Madsen Annulus-Averaged", +# linewidth=4, +# color='tab:red', +# linestyle = "solid", +# alpha = alpha, +# ) +ax0.plot( + wind_speeds, + floris_Ct_rotor_umm, + label="FLORIS-MITRotor UMM Rotor-Averaged", + linewidth=4, + color='tab:blue', + linestyle = "dashed", + alpha = alpha, +) +ax0.plot( + wind_speeds, + floris_Ct_annulus_umm, + label="FLORIS-MITRotor UMM Annulus-Averaged", + linewidth=4, + color='tab:green', + linestyle = "dashed", + alpha = alpha, ) -ax.set_xlabel("Wind Speed [m/s]") +ax0.plot( + wind_speeds, + floris_Ct_rotor_madsen, + label="FLORIS-MITRotor Madsen Rotor-Averaged", + linewidth=4, + color='tab:purple', + linestyle = "dashed", + alpha = alpha, +) +ax0.plot( + wind_speeds, + floris_Ct_annulus_madsen, + label="FLORIS-MITRotor Madsen Annulus-Averaged", + linewidth=4, + color='tab:red', + linestyle = "dashed", + alpha = alpha, +) +ax0.set_xlabel("Wind Speed [m/s]", size = 16) +ax0.set_ylabel("$C_T$", size = 16) +ax0.tick_params(labelsize = 14) +ax0.set_title("$C_T$", size = 18) # plot Cp values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) -ax.plot( +ax1.plot( wind_table, df["Aero Power Coefficient [-]"].to_list(), - label="IEA15MW $C_P$", - linewidth=2, - color='tab:blue', - linestyle = "solid" + label="IEA15MW", + linewidth=4, + color='tab:orange', + linestyle = "solid", + alpha = alpha, ) -ax.plot( +ax1.plot( wind_speeds, - mit_Cp, - label="MITRotor $C_P$", - linewidth=2, + mit_Cp_rotor_umm, + label="MITRotor UMM Rotor-Averaged", + linewidth=4, color='tab:blue', - linestyle = "dashed" + linestyle = "solid", + alpha = alpha, ) -ax.plot( +ax1.plot( + wind_speeds, + mit_Cp_annulus_umm, + label="MITRotor UMM Annulus-Averaged", + linewidth=4, + color='tab:green', + linestyle = "solid", + alpha = alpha, +) +# ax1.plot( +# wind_speeds, +# mit_Cp_rotor_madsen, +# label="MITRotor Madsen Rotor-Averaged", +# linewidth=4, +# color='tab:purple', +# linestyle = "solid", +# alpha = alpha, +# ) +# ax1.plot( +# wind_speeds, +# mit_Cp_annulus_madsen, +# label="MITRotor Madsen Annulus-Averaged", +# linewidth=4, +# color='tab:red', +# linestyle = "solid", +# alpha = alpha, +# ) +ax1.plot( wind_speeds, - floris_Cp, - label="FLORIS $C_P$", - linewidth=2, + floris_Cp_rotor_umm, + label="FLORIS-MITRotor UMM Rotor-Averaged", + linewidth=4, color='tab:blue', - linestyle = "dotted" + linestyle = "dashed", + alpha = alpha, +) +ax1.plot( + wind_speeds, + floris_Cp_annulus_umm, + label="FLORIS-MITRotor UMM Annulus-Averaged", + linewidth=4, + color='tab:green', + linestyle = "dashed", + alpha = alpha, +) +ax1.plot( + wind_speeds, + floris_Cp_rotor_madsen, + label="FLORIS-MITRotor Madsen Rotor-Averaged", + linewidth=4, + color='tab:purple', + linestyle = "dashed", + alpha = alpha, +) +ax1.plot( + wind_speeds, + floris_Cp_annulus_madsen, + label="FLORIS-MITRotor Madsen Annulus-Averaged", + linewidth=4, + color='tab:red', + linestyle = "dashed", + alpha = alpha, ) -ax.set_title("IEA 15 MW FLORIS Interface Validation", size = 18) -ax.set_xlabel("Wind Speed [m/s]", size = 16) -ax.tick_params(labelsize=14) -ax.legend(fontsize = 14) -plt.savefig(figdir / "example_5_IEA15mw_CT_CP.png", dpi=300) +ax1.set_xlabel("Wind Speed [m/s]", size = 16) +ax1.set_ylabel("$C_P$", size = 16) +ax1.tick_params(labelsize = 14) +ax1.set_title("$C_P$", size = 18) +ax1.legend( + fontsize=14, + loc="upper right", +) + +plt.savefig(figdir / "example_5_IEA15mw_CT_CP.png", dpi=300) From daa0d95cdf177a3c70f57a8a8d008f99119b96c9 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Sat, 28 Feb 2026 13:01:20 -0500 Subject: [PATCH 14/50] Remove interpolation of setpoints from timing --- examples/example_05_floris_integration.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/example_05_floris_integration.py b/examples/example_05_floris_integration.py index f4baae4..e26e5e8 100644 --- a/examples/example_05_floris_integration.py +++ b/examples/example_05_floris_integration.py @@ -59,7 +59,7 @@ df = pl.read_csv(csv_file) wind_table = df["Wind [m/s]"].to_numpy() -wind_speeds = np.linspace(3, 25, 50) +wind_speeds = np.linspace(5, 25, 20) wind_dirs = np.full_like(wind_speeds, 270.0) turbulence_intensity = np.zeros_like(wind_speeds) @@ -104,9 +104,10 @@ # -------- plot CT and CP values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) ------- # solve UMM-BEM though MITRotor - rotor averaged +pitches_rad = np.deg2rad(pitches) bem_rotor_umm = default_bem_factory() mit_rotor_umm_start = time.time() -mit_sols_rotor_umm = [bem_rotor_umm(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] +mit_sols_rotor_umm = [bem_rotor_umm(pitch=pitches_rad[i], tsr=tsrs[i], yaw=0, tilt=0) for i in range(len(tsrs))] mit_rotor_umm_end = time.time() mit_Ct_rotor_umm = [sol.Ct() for sol in mit_sols_rotor_umm] mit_Cp_rotor_umm = [sol.Cp() for sol in mit_sols_rotor_umm] @@ -120,7 +121,7 @@ tiploss_model=NoTipLoss(), ) mit_annulus_umm_start = time.time() -mit_sols_annulus_umm = [bem_annulus_umm(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] +mit_sols_annulus_umm = [bem_annulus_umm(pitch=pitches_rad[i], tsr=tsrs[i], yaw=0, tilt=0) for i in range(len(tsrs))] mit_annulus_umm_end = time.time() mit_Ct_annulus_umm = [sol.Ct() for sol in mit_sols_annulus_umm] mit_Cp_annulus_umm = [sol.Cp() for sol in mit_sols_annulus_umm] From a5856409dacdb6eac03c2d2dfef8ed9eb08756c1 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Sun, 1 Mar 2026 12:18:30 -0500 Subject: [PATCH 15/50] Updated example 6 for non-vectorized code --- ...on.py => example_06_floris_integration.py} | 276 ++++++++---------- examples/example_timing.py | 12 + 2 files changed, 140 insertions(+), 148 deletions(-) rename examples/{example_05_floris_integration.py => example_06_floris_integration.py} (58%) create mode 100644 examples/example_timing.py diff --git a/examples/example_05_floris_integration.py b/examples/example_06_floris_integration.py similarity index 58% rename from examples/example_05_floris_integration.py rename to examples/example_06_floris_integration.py index e26e5e8..455c23d 100644 --- a/examples/example_05_floris_integration.py +++ b/examples/example_06_floris_integration.py @@ -19,7 +19,7 @@ # MITRotor / UMM Imports from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp from MITRotor.ReferenceTurbines import IEA15MW -from MITRotor.Momentum import UnifiedMomentum, MadsenMomentum +from MITRotor.Momentum import UnifiedMomentum, UnifiedMomentumLUT from MITRotor.Geometry import BEMGeometry from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM @@ -100,14 +100,17 @@ ax.set_xlabel("Wind Speed [m/s]", size = 16) ax.tick_params(labelsize=14) ax.legend(fontsize = 14) -plt.savefig(figdir / "example_5_pitch_tsr_interpolation.png", dpi=300) +plt.savefig(figdir / "example_6_pitch_tsr_interpolation.png", dpi=300) # -------- plot CT and CP values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) ------- # solve UMM-BEM though MITRotor - rotor averaged pitches_rad = np.deg2rad(pitches) bem_rotor_umm = default_bem_factory() mit_rotor_umm_start = time.time() -mit_sols_rotor_umm = [bem_rotor_umm(pitch=pitches_rad[i], tsr=tsrs[i], yaw=0, tilt=0) for i in range(len(tsrs))] +pitches = np.deg2rad(pitch_interp(wind_speeds)) +tsrs = tsr_interp(wind_speeds) +yaws, tilts = np.zeros_like(pitches), np.zeros_like(pitches) +mit_sols_rotor_umm = [bem_rotor_umm(pitch=pitches[i], tsr=tsrs[i], yaw=yaws[i], tilt=tilts[i]) for i in range(len(pitches))] mit_rotor_umm_end = time.time() mit_Ct_rotor_umm = [sol.Ct() for sol in mit_sols_rotor_umm] mit_Cp_rotor_umm = [sol.Cp() for sol in mit_sols_rotor_umm] @@ -121,39 +124,40 @@ tiploss_model=NoTipLoss(), ) mit_annulus_umm_start = time.time() -mit_sols_annulus_umm = [bem_annulus_umm(pitch=pitches_rad[i], tsr=tsrs[i], yaw=0, tilt=0) for i in range(len(tsrs))] +mit_sols_annulus_umm = [bem_annulus_umm(pitch=pitches[i], tsr=tsrs[i], yaw=yaws[i], tilt=tilts[i]) for i in range(len(pitches))] mit_annulus_umm_end = time.time() mit_Ct_annulus_umm = [sol.Ct() for sol in mit_sols_annulus_umm] mit_Cp_annulus_umm = [sol.Cp() for sol in mit_sols_annulus_umm] print("MITRotor UMM-BEM Annulus-Averaged: " + str(mit_annulus_umm_end - mit_annulus_umm_start) + " seconds") -# solve Madsen-BEM though MITRotor - rotor averaged -bem_rotor_madesen = BEM( - rotor=IEA15MW(), - momentum_model=MadsenMomentum(averaging="rotor"), - geometry=BEMGeometry(Nr=10, Ntheta=20), - tiploss_model=NoTipLoss() - ) -mit_rotor_madsen_start = time.time() -mit_sols_rotor_madsen = [bem_rotor_madesen(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] -mit_rotor_madsen_end = time.time() -mit_Ct_rotor_madsen = [sol.Ct() for sol in mit_sols_rotor_madsen] -mit_Cp_rotor_madsen = [sol.Cp() for sol in mit_sols_rotor_madsen] -print("MITRotor Madsen-BEM Rotor-Averaged: " + str(mit_rotor_madsen_end - mit_rotor_madsen_start) + " seconds") +# solve UMM-BEM though MITRotor - sector averaged +# bem_sector_umm = BEM( +# rotor=IEA15MW(), +# momentum_model=UnifiedMomentum(averaging="sector"), +# geometry=BEMGeometry(Nr=10, Ntheta=20), +# tiploss_model=NoTipLoss(), +# ) +# mit_sector_umm_start = time.time() +# mit_sols_sector_umm = bem_sector_umm(pitch=pitches, tsr=tsrs, yaw=yaws, tilt=tilts) +# mit_sector_umm_end = time.time() +# mit_Ct_sector_umm = mit_sols_sector_umm.Ct() +# mit_Cp_sector_umm = mit_sols_sector_umm.Cp() +# print("MITRotor UMM-BEM Sector-Averaged: " + str(mit_sector_umm_end - mit_sector_umm_start) + " seconds") -# solve Madsen-BEM though MITRotor - annulus averaged -bem_annulus_madesen = BEM( - rotor=IEA15MW(), - momentum_model=MadsenMomentum(averaging="annulus"), - geometry=BEMGeometry(Nr=10, Ntheta=20), - tiploss_model=NoTipLoss() - ) -mit_annulus_madsen_start = time.time() -mit_sols_annulus_madsen = [bem_annulus_madesen(pitch=np.deg2rad(pitch_interp(u)), tsr=tsr_interp(u), yaw=0, tilt=0) for u in wind_speeds] -mit_annulus_madsen_end = time.time() -mit_Ct_annulus_madsen = [sol.Ct() for sol in mit_sols_annulus_madsen] -mit_Cp_annulus_madsen = [sol.Cp() for sol in mit_sols_annulus_madsen] -print("MITRotor Madsen-BEM Annulus-Averaged: " + str(mit_annulus_madsen_end - mit_annulus_madsen_start) + " seconds") +# solve UMM-BEM with LUT though MITRotor - annulus averaged +print("Making LUT!") +bem_annulus_umm_LUT = BEM( + rotor=IEA15MW(), + momentum_model=UnifiedMomentumLUT(averaging="annulus", cache_fn = Path("cache")/ "lut.csv"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss(), +) +mit_annulus_umm_LUT_start = time.time() +mit_sols_annulus_umm_LUT = [bem_annulus_umm_LUT(pitch=pitches[i], tsr=tsrs[i], yaw=yaws[i], tilt=tilts[i]) for i in range(len(pitches))] +mit_annulus_umm_LUT_end = time.time() +mit_Ct_annulus_umm_LUT = [sol.Ct() for sol in mit_sols_annulus_umm_LUT] +mit_Cp_annulus_umm_LUT = [sol.Cp() for sol in mit_sols_annulus_umm_LUT] +print("MITRotor UMM-BEM LUT Annulus-Averaged: " + str(mit_annulus_umm_LUT_end - mit_annulus_umm_LUT_start) + " seconds") # solve FLORIS with UMM-BEM though MITRotor - rotor averaged time_series = TimeSeries( @@ -185,213 +189,189 @@ floris_Cp_annulus_umm = floris_power_annulus_umm / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) print("FLORIS UMM-BEM Annulus-Averaged: " + str(floris_annulus_umm_end - floris_annulus_umm_start) + " seconds") -# solve FLORIS with Madsen-BEM though MITRotor - rotor averaged -fmodel_rotor_madsen = FlorisModel("defaults") -fmodel_rotor_madsen.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) -fmodel_rotor_madsen.set_operation_model(MITRotorTurbine(bem_model = bem_rotor_madesen)) # default bem_model uses rotor-averaging -floris_rotor_madsen_start = time.time() -fmodel_rotor_madsen.run() -floris_rotor_madsen_end = time.time() -floris_Ct_rotor_madsen = fmodel_rotor_madsen.get_turbine_thrust_coefficients() -floris_power_rotor_madsen = np.squeeze(fmodel_rotor_madsen.get_turbine_powers()) -floris_Cp_rotor_madsen = floris_power_rotor_madsen / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) -print("FLORIS Madsen-BEM Rotor-Averaged: " + str(floris_rotor_madsen_end - floris_rotor_madsen_start) + " seconds") +# solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged +fmodel_annulus_umm_LUT = FlorisModel("defaults") +fmodel_annulus_umm_LUT.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) +fmodel_annulus_umm_LUT.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_umm_LUT)) # default bem_model uses rotor-averaging +floris_annulus_umm_LUT_start = time.time() +fmodel_annulus_umm_LUT.run() +floris_annulus_umm_LUT_end = time.time() +floris_Ct_annulus_umm_LUT = fmodel_annulus_umm_LUT.get_turbine_thrust_coefficients() +floris_power_annulus_umm_LUT = np.squeeze(fmodel_annulus_umm_LUT.get_turbine_powers()) +floris_Cp_annulus_umm_LUT = floris_power_annulus_umm_LUT / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +print("FLORIS UMM-BEM LUT Annulus-Averaged: " + str(floris_annulus_umm_LUT_end - floris_annulus_umm_LUT_start) + " seconds") -# solve FLORIS with Madsen-BEM though MITRotor - annulus averaged -fmodel_annulus_madsen = FlorisModel("defaults") -fmodel_annulus_madsen.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) -fmodel_annulus_madsen.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_madesen)) # default bem_model uses rotor-averaging -floris_annulus_madsen_start = time.time() -fmodel_annulus_madsen.run() -floris_annulus_madsen_end = time.time() -floris_Ct_annulus_madsen = fmodel_annulus_madsen.get_turbine_thrust_coefficients() -floris_power_annulus_madsen = np.squeeze(fmodel_annulus_madsen.get_turbine_powers()) -floris_Cp_annulus_madsen = floris_power_annulus_madsen / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) -print("FLORIS Madsen-BEM Annulus-Averaged: " + str(floris_annulus_madsen_end - floris_annulus_madsen_start) + " seconds") +# Presentation-friendly typography +plt.rcParams.update({ + "font.size": 20, + "axes.titlesize": 20, + "axes.labelsize": 22, + "xtick.labelsize": 20, + "ytick.labelsize": 20, +}) # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) -fig, (ax0, ax1) = plt.subplots(figsize=(16, 8), ncols = 2, sharex = True, sharey = True) -fig.suptitle("IEA 15 MW FLORIS Interface Validation", size = 18) -alpha = 0.8 +fig, (ax0, ax1) = plt.subplots(figsize=(17, 9), ncols = 2, sharex = True, sharey = True) +fig.suptitle("IEA 15 MW FLORIS Interface Validation") +alpha = 0.6 ax0.plot( wind_table, df["Thrust Coefficient [-]"].to_list(), - linewidth=4, + linewidth=6, label="IEA15MW", color='tab:orange', linestyle = "solid", alpha = alpha, + zorder = 1, ) ax0.plot( wind_speeds, mit_Ct_rotor_umm, label="MITRotor UMM Rotor-Averaged", - linewidth=4, + linewidth=6, color='tab:blue', linestyle = "solid", alpha = alpha, + zorder = 1, ) +ax0.plot( + wind_speeds, + mit_Ct_annulus_umm_LUT, + label="MITRotor UMM LUT Annulus-Averaged", + linewidth=6, + color='tab:red', + linestyle = "solid", + alpha = alpha, + zorder = 1, +) + ax0.plot( wind_speeds, mit_Ct_annulus_umm, label="MITRotor UMM Annulus-Averaged", - linewidth=4, + linewidth=6, color='tab:green', linestyle = "solid", alpha = alpha, + zorder = 1, ) -# ax0.plot( -# wind_speeds, -# mit_Ct_rotor_madsen, -# label="MITRotor Madsen Rotor-Averaged", -# linewidth=4, -# color='tab:purple', -# linestyle = "solid", -# alpha = alpha, -# ) -# ax0.plot( -# wind_speeds, -# mit_Ct_annulus_madsen, -# label="MITRotor Madsen Annulus-Averaged", -# linewidth=4, -# color='tab:red', -# linestyle = "solid", -# alpha = alpha, -# ) -ax0.plot( + +ax0.scatter( wind_speeds, floris_Ct_rotor_umm, label="FLORIS-MITRotor UMM Rotor-Averaged", - linewidth=4, color='tab:blue', - linestyle = "dashed", alpha = alpha, + marker = "o", + zorder = 2, + s = 80, ) -ax0.plot( +ax0.scatter( wind_speeds, floris_Ct_annulus_umm, label="FLORIS-MITRotor UMM Annulus-Averaged", - linewidth=4, color='tab:green', - linestyle = "dashed", alpha = alpha, + zorder = 2, + s = 80, + marker = "s" ) - -ax0.plot( +ax0.scatter( wind_speeds, - floris_Ct_rotor_madsen, - label="FLORIS-MITRotor Madsen Rotor-Averaged", - linewidth=4, - color='tab:purple', - linestyle = "dashed", - alpha = alpha, -) -ax0.plot( - wind_speeds, - floris_Ct_annulus_madsen, - label="FLORIS-MITRotor Madsen Annulus-Averaged", - linewidth=4, + floris_Ct_annulus_umm_LUT, + label="FLORIS-MITRotor UMM LUT Annulus-Averaged", color='tab:red', - linestyle = "dashed", alpha = alpha, + zorder = 2, + s = 80, + marker = "v" ) -ax0.set_xlabel("Wind Speed [m/s]", size = 16) -ax0.set_ylabel("$C_T$", size = 16) -ax0.tick_params(labelsize = 14) -ax0.set_title("$C_T$", size = 18) +ax0.set_xlabel("Wind Speed [m/s]") +ax0.set_ylabel("$C_T$") +ax0.tick_params() +ax0.set_title("$C_T$") # plot Cp values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) ax1.plot( wind_table, df["Aero Power Coefficient [-]"].to_list(), label="IEA15MW", - linewidth=4, + linewidth=6, color='tab:orange', linestyle = "solid", alpha = alpha, + zorder = 1 ) ax1.plot( wind_speeds, mit_Cp_rotor_umm, label="MITRotor UMM Rotor-Averaged", - linewidth=4, + linewidth=6, color='tab:blue', linestyle = "solid", alpha = alpha, + zorder = 1 +) +ax1.plot( + wind_speeds, + mit_Cp_annulus_umm_LUT, + label="MITRotor UMM LUT Annulus-Averaged", + linewidth=6, + color='tab:red', + linestyle = "solid", + alpha = alpha, + zorder = 1 ) ax1.plot( wind_speeds, mit_Cp_annulus_umm, label="MITRotor UMM Annulus-Averaged", - linewidth=4, + linewidth=6, color='tab:green', linestyle = "solid", alpha = alpha, + zorder = 1 ) -# ax1.plot( -# wind_speeds, -# mit_Cp_rotor_madsen, -# label="MITRotor Madsen Rotor-Averaged", -# linewidth=4, -# color='tab:purple', -# linestyle = "solid", -# alpha = alpha, -# ) -# ax1.plot( -# wind_speeds, -# mit_Cp_annulus_madsen, -# label="MITRotor Madsen Annulus-Averaged", -# linewidth=4, -# color='tab:red', -# linestyle = "solid", -# alpha = alpha, -# ) -ax1.plot( + +ax1.scatter( wind_speeds, floris_Cp_rotor_umm, label="FLORIS-MITRotor UMM Rotor-Averaged", - linewidth=4, color='tab:blue', - linestyle = "dashed", + marker = "o", alpha = alpha, + s = 80, + zorder = 2 ) -ax1.plot( +ax1.scatter( wind_speeds, floris_Cp_annulus_umm, label="FLORIS-MITRotor UMM Annulus-Averaged", - linewidth=4, color='tab:green', - linestyle = "dashed", + marker = "s", alpha = alpha, + s = 80, + zorder = 2 ) -ax1.plot( - wind_speeds, - floris_Cp_rotor_madsen, - label="FLORIS-MITRotor Madsen Rotor-Averaged", - linewidth=4, - color='tab:purple', - linestyle = "dashed", - alpha = alpha, -) -ax1.plot( +ax1.scatter( wind_speeds, - floris_Cp_annulus_madsen, - label="FLORIS-MITRotor Madsen Annulus-Averaged", - linewidth=4, + floris_Cp_annulus_umm_LUT, + label="FLORIS-MITRotor UMM LUT Annulus-Averaged", color='tab:red', - linestyle = "dashed", + marker = "v", alpha = alpha, + s = 80, + zorder = 2 ) -ax1.set_xlabel("Wind Speed [m/s]", size = 16) -ax1.set_ylabel("$C_P$", size = 16) -ax1.tick_params(labelsize = 14) -ax1.set_title("$C_P$", size = 18) +ax1.set_xlabel("Wind Speed [m/s]") +ax1.set_ylabel("$C_P$") +ax1.set_title("$C_P$") ax1.legend( - fontsize=14, + fontsize=16, loc="upper right", ) -plt.savefig(figdir / "example_5_IEA15mw_CT_CP.png", dpi=300) +plt.savefig(figdir / "example_6_IEA15mw_CT_CP.png", dpi=300) \ No newline at end of file diff --git a/examples/example_timing.py b/examples/example_timing.py new file mode 100644 index 0000000..b3d628f --- /dev/null +++ b/examples/example_timing.py @@ -0,0 +1,12 @@ +import numpy as np +import polars as pl +import pytest +from pathlib import Path +import matplotlib.pyplot as plt +from MITRotor.Momentum import UnifiedMomentumLUT, UnifiedMomentum +from MITRotor import BEM, IEA15MW, BEMGeometry +import time + + +# use the same (easily convering example and up the number of setpoints and see how it scales) +# try a range of examples and see how slowly they converge \ No newline at end of file From f6f036889e48add64a58ca119fa14fcee889e94d Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Sun, 1 Mar 2026 12:56:12 -0500 Subject: [PATCH 16/50] Add in example timing script --- examples/example_timing.py | 81 +++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/examples/example_timing.py b/examples/example_timing.py index b3d628f..7f424d5 100644 --- a/examples/example_timing.py +++ b/examples/example_timing.py @@ -1,12 +1,83 @@ import numpy as np -import polars as pl -import pytest from pathlib import Path -import matplotlib.pyplot as plt from MITRotor.Momentum import UnifiedMomentumLUT, UnifiedMomentum +from MITRotor.TipLoss import NoTipLoss from MITRotor import BEM, IEA15MW, BEMGeometry +import pandas as pd import time +# Floris imports +from floris import FlorisModel, TimeSeries +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory -# use the same (easily convering example and up the number of setpoints and see how it scales) -# try a range of examples and see how slowly they converge \ No newline at end of file +bem_rotor_umm = MITRotorTurbine() +bem_annulus_umm_LUT = BEM( + rotor=IEA15MW(), + momentum_model=UnifiedMomentumLUT(averaging="annulus", cache_fn = Path("cache")/ "lut.csv"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss(), +) + +bem_rotor_times = [] +bem_annulus_LUT_times = [] +ns = [5 * i for i in range(1, 20)] +for n in ns: + print(f"{n} wind speeds") + wind_speeds = np.linspace(5, 20, n) + wind_dirs = np.full_like(wind_speeds, 270.0) + turbulence_intensity = np.zeros_like(wind_speeds) + + time_series = TimeSeries( + wind_speeds=wind_speeds, + wind_directions=wind_dirs, + turbulence_intensities=turbulence_intensity, + ) + + fmodel_rotor_umm = FlorisModel("defaults") + fmodel_rotor_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_rotor_umm.set_operation_model(bem_rotor_umm) # default bem_model uses rotor-averaging + floris_rotor_umm_start = time.time() + fmodel_rotor_umm.run() + floris_rotor_umm_end = time.time() + dt_rotor = floris_rotor_umm_end - floris_rotor_umm_start + print("FLORIS UMM-BEM Rotor-Averaged: " + str(dt_rotor) + " seconds") + bem_rotor_times.append(dt_rotor) + + # solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged + fmodel_annulus_umm_LUT = FlorisModel("defaults") + fmodel_annulus_umm_LUT.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_annulus_umm_LUT.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_umm_LUT)) # default bem_model uses rotor-averaging + floris_annulus_umm_LUT_start = time.time() + fmodel_annulus_umm_LUT.run() + floris_annulus_umm_LUT_end = time.time() + dt_annulus_LUT = floris_annulus_umm_LUT_end - floris_annulus_umm_LUT_start + print("FLORIS UMM-BEM LUT Annulus-Averaged: " + str(dt_annulus_LUT) + " seconds") + bem_annulus_LUT_times.append(dt_annulus_LUT) + + +rows = [] + +for n, dt in zip(ns, bem_rotor_times): + rows.append({ + "n_wind_speeds": n, + "runtime_seconds": dt, + "model": "rotor_umm", + "vectorized": False + }) + +for n, dt in zip(ns, bem_annulus_LUT_times): + rows.append({ + "n_wind_speeds": n, + "runtime_seconds": dt, + "model": "annulus_lut", + "vectorized": False + }) + +df = pd.DataFrame(rows) + +csv_path = Path("cache")/ "timing_results.csv" + +if csv_path.exists(): + df.to_csv(csv_path, mode="a", header=False, index=False) +else: + df.to_csv(csv_path, index=False) \ No newline at end of file From b2c1094c56810242766eccc99a56c6fcb7742ea2 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Sun, 1 Mar 2026 14:09:13 -0500 Subject: [PATCH 17/50] Add in plotting code and fix errors in timing code --- examples/example_timing.py | 60 ++++++++++++++++--- examples/example_timing_plots.py | 99 ++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 examples/example_timing_plots.py diff --git a/examples/example_timing.py b/examples/example_timing.py index 7f424d5..169e3d7 100644 --- a/examples/example_timing.py +++ b/examples/example_timing.py @@ -10,22 +10,29 @@ from floris import FlorisModel, TimeSeries from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory -bem_rotor_umm = MITRotorTurbine() +bem_rotor_umm = default_bem_factory() bem_annulus_umm_LUT = BEM( rotor=IEA15MW(), momentum_model=UnifiedMomentumLUT(averaging="annulus", cache_fn = Path("cache")/ "lut.csv"), geometry=BEMGeometry(Nr=10, Ntheta=20), tiploss_model=NoTipLoss(), ) +rotor_area = np.pi * bem_rotor_umm.rotor.R**2 bem_rotor_times = [] bem_annulus_LUT_times = [] -ns = [5 * i for i in range(1, 20)] +wind_speeds_all = [] +bem_rotor_values = [] +bem_annulus_LUT_values = [] +ns = [5 * i for i in range(1, 21)] for n in ns: print(f"{n} wind speeds") wind_speeds = np.linspace(5, 20, n) wind_dirs = np.full_like(wind_speeds, 270.0) turbulence_intensity = np.zeros_like(wind_speeds) + wind_speeds_all.extend( + np.squeeze(wind_speeds) + ) time_series = TimeSeries( wind_speeds=wind_speeds, @@ -35,13 +42,17 @@ fmodel_rotor_umm = FlorisModel("defaults") fmodel_rotor_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) - fmodel_rotor_umm.set_operation_model(bem_rotor_umm) # default bem_model uses rotor-averaging + fmodel_rotor_umm.set_operation_model(MITRotorTurbine(bem_model = bem_rotor_umm)) # default bem_model uses rotor-averaging floris_rotor_umm_start = time.time() fmodel_rotor_umm.run() floris_rotor_umm_end = time.time() dt_rotor = floris_rotor_umm_end - floris_rotor_umm_start print("FLORIS UMM-BEM Rotor-Averaged: " + str(dt_rotor) + " seconds") bem_rotor_times.append(dt_rotor) + floris_Cp_rotor_umm = np.squeeze(fmodel_rotor_umm.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) + bem_rotor_values.extend( + np.squeeze(floris_Cp_rotor_umm) + ) # solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged fmodel_annulus_umm_LUT = FlorisModel("defaults") @@ -53,8 +64,13 @@ dt_annulus_LUT = floris_annulus_umm_LUT_end - floris_annulus_umm_LUT_start print("FLORIS UMM-BEM LUT Annulus-Averaged: " + str(dt_annulus_LUT) + " seconds") bem_annulus_LUT_times.append(dt_annulus_LUT) + floris_Cp_annulus_umm_LUT = np.squeeze(fmodel_annulus_umm_LUT.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) + bem_annulus_LUT_values.extend( + np.squeeze(floris_Cp_annulus_umm_LUT) + ) - +# make timing CSV +vectorized = False rows = [] for n, dt in zip(ns, bem_rotor_times): @@ -62,7 +78,7 @@ "n_wind_speeds": n, "runtime_seconds": dt, "model": "rotor_umm", - "vectorized": False + "vectorized": vectorized }) for n, dt in zip(ns, bem_annulus_LUT_times): @@ -70,7 +86,7 @@ "n_wind_speeds": n, "runtime_seconds": dt, "model": "annulus_lut", - "vectorized": False + "vectorized": vectorized }) df = pd.DataFrame(rows) @@ -80,4 +96,34 @@ if csv_path.exists(): df.to_csv(csv_path, mode="a", header=False, index=False) else: - df.to_csv(csv_path, index=False) \ No newline at end of file + df.to_csv(csv_path, index=False) + +# make values CSV +rows = [] +# Rotor +for wind, val in zip(wind_speeds_all, bem_rotor_values): + rows.append({ + "wind_speed": wind, + "power": val, + "model": "rotor_umm", + "vectorized": vectorized + }) + +# Annulus LUT +for wind, val in zip(wind_speeds_all, bem_annulus_LUT_values): + rows.append({ + "wind_speed": wind, + "power": val, + "model": "annulus_lut", + "vectorized": vectorized + }) + +df = pd.DataFrame(rows) + +csv_path = Path("cache") / "value_results.csv" + +if csv_path.exists(): + df.to_csv(csv_path, mode="a", header=False, index=False) +else: + df.to_csv(csv_path, index=False) + diff --git a/examples/example_timing_plots.py b/examples/example_timing_plots.py new file mode 100644 index 0000000..3e52526 --- /dev/null +++ b/examples/example_timing_plots.py @@ -0,0 +1,99 @@ +import pandas as pd +import matplotlib.pyplot as plt +from pathlib import Path + +# ---- Load data ---- +figdir = Path("fig") +time_df = pd.read_csv(Path("cache")/ "timing_results.csv") +value_df = pd.read_csv(Path("cache")/ "value_results.csv") + +#------------------------------------ +# Timing plot +#------------------------------------ +df_avg = ( + time_df.groupby(["n_wind_speeds", "model", "vectorized"], as_index=False) + .agg( + runtime_mean=("runtime_seconds", "mean"), + runtime_std=("runtime_seconds", "std"), + ) +) + +# ---- Create label column for plotting ---- +def make_label(row): + base = { + "rotor_umm": "UMM Rotor-Averaged", + "annulus_lut": "UMM LUT Annulus-Averaged", + }[row["model"]] + + if row["vectorized"]: + return base + " (Vectorized)" + else: + return base + +df_avg["label"] = df_avg.apply(make_label, axis=1) + +label_order = [ + "UMM Rotor-Averaged", + "UMM LUT Annulus-Averaged", + "UMM Rotor-Averaged (Vectorized)", + "UMM LUT Annulus-Averaged (Vectorized)", +] + +# ---- Plot ---- +plt.figure(figsize=(8, 6)) + +for label in label_order: + group = df_avg[df_avg["label"] == label] + group = group.sort_values("n_wind_speeds") + + plt.errorbar( + group["n_wind_speeds"], + group["runtime_mean"], + yerr=group["runtime_std"], + marker="o", + capsize=3, + label=label, + ) + +plt.xlabel("Number of Wind Speeds") +plt.ylabel("Runtime (seconds)") +plt.title("Runtime vs Number of Wind Speeds") +plt.legend() +plt.grid(True) +plt.tight_layout() +plt.savefig(figdir / "example_timings.png", dpi=300) + +#------------------------------------ +# Value plot +#------------------------------------ +plt.figure(figsize=(8, 6)) + +df_avg = ( + value_df.groupby(["wind_speed", "model", "vectorized"], as_index=False) + .agg( + power_mean=("power", "mean"), + power_std=("power", "std"), + ) +) +df_avg["label"] = df_avg.apply(make_label, axis=1) + +for label in label_order: + group = df_avg[df_avg["label"] == label] + group = group.sort_values("wind_speed") + + plt.errorbar( + group["wind_speed"], + group["power_mean"], + yerr=group["power_std"], + marker="o", + capsize=3, + label=label, + ) + +plt.xlabel("Wind Speed") +plt.ylabel("Coefficent of Power $C_P$") +plt.title("$C_P$ vs Wind Speed") +plt.legend() +plt.grid(True) +plt.tight_layout() +plt.savefig(figdir / "example_values.png", dpi=300) \ No newline at end of file From 3659c291c9747e40c79c57d6ba32293dd39fbda5 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Sun, 1 Mar 2026 14:22:25 -0500 Subject: [PATCH 18/50] Update timing plots --- examples/example_timing_plots.py | 37 +++++++++++++++----------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/examples/example_timing_plots.py b/examples/example_timing_plots.py index 3e52526..0bc9835 100644 --- a/examples/example_timing_plots.py +++ b/examples/example_timing_plots.py @@ -40,7 +40,7 @@ def make_label(row): ] # ---- Plot ---- -plt.figure(figsize=(8, 6)) +plt.figure(figsize=(6, 4)) for label in label_order: group = df_avg[df_avg["label"] == label] @@ -53,9 +53,11 @@ def make_label(row): marker="o", capsize=3, label=label, + linewidth = 2, ) + # plt.yscale("log") -plt.xlabel("Number of Wind Speeds") +plt.xlabel("Number of Wind Speeds Run\n(evenly-spaced between 5-20 m/s)") plt.ylabel("Runtime (seconds)") plt.title("Runtime vs Number of Wind Speeds") plt.legend() @@ -66,32 +68,27 @@ def make_label(row): #------------------------------------ # Value plot #------------------------------------ -plt.figure(figsize=(8, 6)) +plt.figure(figsize=(6, 4)) -df_avg = ( - value_df.groupby(["wind_speed", "model", "vectorized"], as_index=False) - .agg( - power_mean=("power", "mean"), - power_std=("power", "std"), - ) -) -df_avg["label"] = df_avg.apply(make_label, axis=1) +value_df["label"] = value_df.apply(make_label, axis=1) for label in label_order: - group = df_avg[df_avg["label"] == label] + group = value_df[value_df["label"] == label] group = group.sort_values("wind_speed") - - plt.errorbar( + is_vectorized = group["vectorized"].iloc[0] + linestyle = "dashed" if is_vectorized else "solid" + zorder = 2 if is_vectorized else 1 + plt.plot( group["wind_speed"], - group["power_mean"], - yerr=group["power_std"], - marker="o", - capsize=3, + group["power"], + linewidth = 3, label=label, + linestyle = linestyle, + zorder = zorder, ) -plt.xlabel("Wind Speed") -plt.ylabel("Coefficent of Power $C_P$") +plt.xlabel("Wind Speed [m/s]") +plt.ylabel("Coefficent of Power ($C_P$)") plt.title("$C_P$ vs Wind Speed") plt.legend() plt.grid(True) From 57ff90faa7530a4f02cdfd1e508e46e704651046 Mon Sep 17 00:00:00 2001 From: Skylar A Gering Date: Fri, 10 Apr 2026 11:07:31 -0400 Subject: [PATCH 19/50] MIT Rotor Vectorization (#20) * Attempt at vecotization in pre-process * Working through initial 2 turbine test * Working with 10x speedup for rotor, 2x slowdown for annulus * Vectorization working with Np as the first axis * Fixed some tests with float input, but needs more work * Updated example 6 to include LUT example * Time vectorized code * Fix example timing script * All tests pass, other than new dimensional tests * Vectorization complete * Clean up BEM tests --- MITRotor/Aerodynamics.py | 11 +- MITRotor/BEMSolver.py | 88 ++++++++---- MITRotor/FlorisInterface/FlorisInterface.py | 27 ++-- MITRotor/Geometry.py | 53 +++++++- MITRotor/Momentum.py | 28 ++-- MITRotor/TangentialInduction.py | 5 +- examples/example_02_rotor_distributions.py | 2 +- .../example_04_yaw_tilt_rotor_comparison.py | 2 +- examples/example_06_floris_integration.py | 20 +-- examples/example_07_LUT_timing.py | 128 ++++++++++++++++++ tests/test_bem.py | 73 +++++++++- 11 files changed, 348 insertions(+), 89 deletions(-) create mode 100644 examples/example_07_LUT_timing.py diff --git a/MITRotor/Aerodynamics.py b/MITRotor/Aerodynamics.py index 265872c..bd761a0 100644 --- a/MITRotor/Aerodynamics.py +++ b/MITRotor/Aerodynamics.py @@ -7,7 +7,7 @@ from numpy.typing import ArrayLike from .RotorDefinition import RotorDefinition -from .Geometry import BEMGeometry +from .Geometry import BEMGeometry, expand_to_Nr_Ntheta from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw __all__ = [ @@ -269,13 +269,16 @@ def __call__( AerodynamicProperties: Calculated aerodynamic properties stored in AerodynamicProperties object. """ + tsr = expand_to_Nr_Ntheta(tsr) + pitch = expand_to_Nr_Ntheta(pitch) # calculate values in "yaw-only" frame local_yaw = -self.eff_yaw Vax = U * ((1 - an) * np.cos(local_yaw)) + theta_eff = geom.theta_mesh + self.delta_theta Vtan = ( (1 + aprime) * tsr * geom.mu_mesh - U * (1 - an) - * np.cos(self.eff_theta_mesh) + * np.cos(theta_eff) * np.sin(local_yaw) ) @@ -291,8 +294,8 @@ def __call__( an = an, aprime = aprime, solidity = solidity, - U = U * np.ones(geom.shape), - wdir = wdir * np.ones(geom.shape), + U = U * np.ones_like(geom.mu_mesh), + wdir = wdir * np.ones_like(geom.mu_mesh), Vax = Vax, Vtan = Vtan, aoa = aoa, diff --git a/MITRotor/BEMSolver.py b/MITRotor/BEMSolver.py index daea9bc..7576268 100644 --- a/MITRotor/BEMSolver.py +++ b/MITRotor/BEMSolver.py @@ -7,12 +7,13 @@ from . import Momentum, TipLoss from .Aerodynamics import AerodynamicModel, AerodynamicProperties, DefaultAerodynamics -from .Geometry import BEMGeometry +from .Geometry import BEMGeometry, expand_to_Np, expand_to_Nr_Ntheta from .RotorDefinition import RotorDefinition from .TangentialInduction import DefaultTangentialInduction, TangentialInductionModel from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw + def average(geometry: BEMGeometry, value: ArrayLike, grid: Literal["sector", "annulus", "rotor"] = "rotor"): # Assuming the function returns a 2D grid of values @@ -58,13 +59,13 @@ def solidity(self, grid: Literal["sector ", "annulus", "rotor"] = "rotor"): def U(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.U, grid) - def wdir(self, grid: Literal["sector ", "annulus", "rotor"] = "rotor"): + def wdir(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.wdir, grid) def Vax(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.Vax, grid) - def Vtan(self, grid: Literal["sector ", "annulus", "rotor"] = "rotor"): + def Vtan(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.Vtan, grid) def W(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): @@ -91,29 +92,27 @@ def Ctan(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): def Cx(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.C_x_corr, grid) - def Ctau(self, grid: Literal["sector ", "annulus", "rotor"] = "rotor"): + def Ctau(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.C_tau_corr, grid) - def Ctau_uncorr(self, grid: Literal["sector ", "annulus", "rotor"] = "rotor"): + def Ctau_uncorr(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.C_tau, grid) def F(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.F, grid) def Cp(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): - dCp = ( - self.tsr - * self.geom.mu_mesh - * self.Ctau_uncorr(grid="sector") - ) + tsr = np.asarray(self.tsr) + if tsr.ndim == 1: + tsr = expand_to_Nr_Ntheta(tsr) + dCp = (tsr * self.geom.mu_mesh * self.Ctau_uncorr(grid="sector")) return average(self.geom, dCp, grid=grid) def Cp_corr(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): - dCp = ( - self.tsr - * self.geom.mu_mesh - * self.Ctau(grid="sector") - ) + tsr = np.asarray(self.tsr) + if tsr.ndim == 1: + tsr = expand_to_Nr_Ntheta(tsr) + dCp = (tsr * self.geom.mu_mesh * self.Ctau(grid="sector")) return average(self.geom, dCp, grid=grid) def Ct(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): @@ -169,21 +168,37 @@ def sample_points(self, yaw: float = 0.0, tilt: float = 0.0) -> tuple[ArrayLike, return X, Y, Z def pre_process(self, pitch, tsr, yaw = 0, tilt = 0, **kwargs): + pitch, tsr = np.asarray(pitch), np.asarray(tsr) + yaw, tilt = np.asarray(yaw), np.asarray(tilt) + self.scalar_inputs = (pitch.ndim == 0) & (tsr.ndim == 0) & (yaw.ndim == 0) & (tilt.ndim == 0) + if not self.scalar_inputs: + assert len(pitch) == len(tsr) == len(yaw) == len(tilt), "Setpoint arrays should be the same lenght" # switch reference frame to a "yaw-only" frame where y' is aligned with the lateral wake - self.aerodynamic_model.eff_yaw = calc_eff_yaw(yaw, tilt) - if tilt == 0: - dtheta = 0 - elif yaw == 0: - dtheta = np.pi / 2 - else: # non-zero yaw and tilt - sin_eff = np.sin(self.aerodynamic_model.eff_yaw) - dtheta = np.arccos(np.sin(yaw) / sin_eff) - self.aerodynamic_model.eff_theta_mesh = self.geometry.theta_mesh + dtheta + yaw, tilt = np.broadcast_arrays(yaw, tilt) + eff_yaw = calc_eff_yaw(yaw, tilt) + # initialize dtheta + dtheta = np.zeros_like(eff_yaw, dtype=float) + # masks + yaw_zero = (yaw == 0) + not_tilt_zero = np.logical_not(tilt == 0) + # case1: yaw == 0 and tilt != 0 + case1 = yaw_zero & not_tilt_zero + dtheta[case1] = np.pi / 2 + # case2: yaw != 0 and tilt != 0 + case2 = np.logical_not(yaw_zero) & not_tilt_zero + dtheta[case2] = np.arccos( + np.sin(yaw[case2]) / np.sin(eff_yaw[case2]) + ) + # expand everything to the correct dimensions to ensure broadcasting + self.aerodynamic_model.eff_yaw = expand_to_Nr_Ntheta(eff_yaw) + self.aerodynamic_model.delta_theta = expand_to_Nr_Ntheta(dtheta) + self.geometry.mu_mesh = expand_to_Np(self.geometry.mu_mesh) + self.geometry.theta_mesh = expand_to_Np(self.geometry.theta_mesh) return def initial_guess(self, *args, **kwargs) -> Tuple[ArrayLike, ...]: - a = (1 / 3) * np.ones(self.geometry.shape) - aprime = np.zeros(self.geometry.shape) + a = (1 / 3) * np.ones_like(self.geometry.mu_mesh) + aprime = np.zeros_like(self.geometry.mu_mesh) return a, aprime @@ -198,8 +213,8 @@ def residual( tilt: ArrayLike = 0.0, ) -> Tuple[ArrayLike, ...]: an, aprime = x - U = np.ones(self.geometry.shape) if U is None else U - wdir = np.zeros(self.geometry.shape) if wdir is None else wdir + U = np.ones_like(self.geometry.mu_mesh) if U is None else U + wdir = np.zeros_like(self.geometry.mu_mesh) if wdir is None else wdir aero_props = self.aerodynamic_model( an = an, @@ -221,12 +236,25 @@ def residual( return e_an, e_aprime def post_process(self, result: FixedPointIterationResult, pitch, tsr, yaw = 0, U=None, wdir=None, tilt = 0.0) -> BEMSolution: - U = np.ones(self.geometry.shape) if U is None else U - wdir = np.zeros(self.geometry.shape) if wdir is None else wdir + U = np.ones_like(self.geometry.mu_mesh) if U is None else U + wdir = np.zeros_like(self.geometry.mu_mesh) if wdir is None else wdir an, aprime = result.x aero_props = self.aerodynamic_model(an, aprime, pitch, tsr, yaw, self.rotor, self.geometry, U, wdir, tilt = tilt) aero_props.F = self.tiploss_model(aero_props, pitch, tsr, yaw, self.rotor, self.geometry, tilt = tilt) avg_Ct = average(self.geometry, aero_props.C_x) u4,v4,w4 = self.momentum_model.compute_initial_wake_velocities(avg_Ct, yaw, tilt = tilt) + if self.scalar_inputs: # if all setpoints were scalars + # return single values as scalars + pitch, tsr, yaw, tilt = [np.asarray(x).item() for x in (pitch, tsr, yaw, tilt)] + u4, v4, w4 = [np.asarray(x).item() for x in (u4, v4, w4)] + # remove unneeded extra axis from Ntheta x Nr arrays + an = np.squeeze(an) + aprime = np.squeeze(aprime) + self.geometry.theta_mesh = np.squeeze(self.geometry.theta_mesh) + self.geometry.mu_mesh = np.squeeze(self.geometry.mu_mesh) + for key, value in vars(aero_props).items(): + if isinstance(value, np.ndarray): + setattr(aero_props, key, np.squeeze(value)) + return BEMSolution(pitch, tsr, yaw, aero_props, self.geometry, result.converged, result.niter, u4, v4, tilt = tilt, w4 = w4) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index f496c69..50c2646 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -109,21 +109,18 @@ def _update_solution(self, # calculate rotor area rotor_area = np.pi * self.bem_model.rotor.R**2 - # loop over flow conditions -> TODO: should this be vectorized? - for findex in range(n_findex): - for tindex in range(n_turbines): - # get setpoints - vel = rotor_average_velocities[findex, tindex] - yaw, tilt = np.deg2rad(yaw_angles[findex, tindex]), np.deg2rad(tilt_angles[findex, tindex]) - pitch = np.deg2rad(self.pitch_interp(vel)) - tsr = self.tsr_interp(vel) - # solve BEM - bem_sol = self.bem_model(pitch, tsr, yaw = yaw, tilt = tilt) - # get induction and thrust coeff - self._a[findex, tindex] = bem_sol.a() - self._Ct[findex, tindex] = bem_sol.Ct() - # compute power - self._power[findex, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (vel)**3 + # get setpoints + yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) + pitch = np.deg2rad(self.pitch_interp(rotor_average_velocities)) + tsr = self.tsr_interp(rotor_average_velocities) + for tindex in range(n_turbines): + # solve BEM + bem_sol = self.bem_model(pitch[:, tindex], tsr[:, tindex], yaw = yaw[:, tindex], tilt = tilt[:, tindex]) + # get induction and thrust coeff + self._a[:, tindex] = bem_sol.a() + self._Ct[:, tindex] = bem_sol.Ct() + # compute power + self._power[:, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_average_velocities[:, tindex])**3 return def power(self, **kwargs) -> NDArrayFloat: diff --git a/MITRotor/Geometry.py b/MITRotor/Geometry.py index 8a00144..7f0ae3f 100644 --- a/MITRotor/Geometry.py +++ b/MITRotor/Geometry.py @@ -40,14 +40,53 @@ def cartesian(self, yaw: float, tilt: float) -> Tuple[ArrayLike, ...]: Z = self.mu_mesh * np.cos(self.theta_mesh) # vertical return X, Y, Z + +# ---------- Function for averaging over the rotor ---------- # - def annulus_average(self, X: ArrayLike): - X_azim = 1 / (2 * np.pi) * np.trapezoid(X, self.theta_mesh, axis=-1) + def annulus_average(self, X): + X = np.asarray(X) + theta = np.asarray(self.theta).reshape(-1) + #Ensure last axis is Nθ + if X.shape[-1] != theta.shape[0]: + raise ValueError(f"Mismatch: X.shape={X.shape}, theta.shape={theta.shape}") + # Integrate over Nθ (last axis) + return (1 / (2 * np.pi)) * np.trapezoid(X, theta, axis=-1) - return X_azim + def rotor_average(self, X): + X = np.asarray(X) + mu = np.asarray(self.mu).reshape(-1) # (Nr,) + # Ensure last axis is Nr + if X.shape[-1] != mu.shape[0]: + raise ValueError(f"Mismatch: X.shape={X.shape}, mu.shape={mu.shape}") + # Integrate over Nr (last axis) + return 2 * np.trapezoid(X * mu, mu, axis=-1) + +# ---------- Function for adjusting axes for vectorization ---------- # - def rotor_average(self, X: ArrayLike): - # Takes annulus average quantities and performs rotor average +def expand_to_Np(x): # add setpoint axis + x = np.atleast_1d(x) + if x.ndim < 3: + return x[None, ...] + else: + return x - X_rotor = 2 * np.trapezoid(X * self.mu, self.mu) - return X_rotor +def expand_to_Nr_Ntheta(x): # add Nr and Nθ axis + x = np.atleast_1d(x) + if x.ndim < 3: + return x[:, None, None] + else: + return x + +def expand_to_Nr(x): # add Nr axis + x = np.atleast_1d(x) + if x.ndim < 2: + return x[:, None] + else: + return x + +def expand_to_Ntheta(x): # add Nθ axis + x = np.atleast_1d(x) + if x.ndim < 3: + return x[:, :, None] + else: + return x diff --git a/MITRotor/Momentum.py b/MITRotor/Momentum.py index edfb4d9..6834ff0 100644 --- a/MITRotor/Momentum.py +++ b/MITRotor/Momentum.py @@ -8,6 +8,7 @@ from pathlib import Path from UnifiedMomentumModel import Momentum as UMM from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw, eff_yaw_inv_rotation +from .Geometry import expand_to_Nr_Ntheta, expand_to_Nr, expand_to_Ntheta if TYPE_CHECKING: from .Geometry import BEMGeometry @@ -62,13 +63,11 @@ def _func_rotor( geom.rotor_average( geom.annulus_average( np.clip(aero_props.C_x_corr, 0, 1.69) - ) - ) + ) + ) ) - - return self.compute_induction(rotor_avg_axial_force, yaw = yaw, tilt = tilt) - - + an = self.compute_induction(rotor_avg_axial_force, yaw = yaw, tilt = tilt) + return expand_to_Nr_Ntheta(an) def _func_annulus( self, @@ -81,15 +80,12 @@ def _func_annulus( tilt: float = 0.0, ) -> ArrayLike: - annulus_avg_axial_force = ( - - geom.annulus_average( - np.clip(aero_props.C_x_corr, -10, 10) - ) - )[:, None] * np.ones(geom.shape) - - - return self.compute_induction(annulus_avg_axial_force, yaw = yaw, tilt = tilt) + annulus_avg_axial_force = geom.annulus_average( + np.clip(aero_props.C_x_corr, 0, 1.69) + ) + yaw, tilt = expand_to_Nr(yaw), expand_to_Nr(tilt) + an = self.compute_induction(annulus_avg_axial_force, yaw = yaw, tilt = tilt) + return expand_to_Ntheta(an) def _func_sector( self, @@ -102,7 +98,7 @@ def _func_sector( tilt: float = 0.0, ) -> ArrayLike: axial_force = np.clip(aero_props.C_x_corr, -10, 10) - + yaw, tilt = expand_to_Nr_Ntheta(yaw), expand_to_Nr_Ntheta(tilt) return self.compute_induction(axial_force, yaw = yaw, tilt = tilt) def __call__( diff --git a/MITRotor/TangentialInduction.py b/MITRotor/TangentialInduction.py index cd493ec..d2dff09 100644 --- a/MITRotor/TangentialInduction.py +++ b/MITRotor/TangentialInduction.py @@ -3,7 +3,7 @@ from numpy.typing import ArrayLike from .Aerodynamics import AerodynamicProperties -from .Geometry import BEMGeometry +from .Geometry import BEMGeometry, expand_to_Nr_Ntheta from .RotorDefinition import RotorDefinition from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw @@ -54,7 +54,8 @@ def __call__( geom: BEMGeometry, tilt: float = 0.0, ) -> ArrayLike: - eff_yaw = calc_eff_yaw(yaw, tilt) + eff_yaw = expand_to_Nr_Ntheta(calc_eff_yaw(yaw, tilt)) + tsr = expand_to_Nr_Ntheta(tsr) aprime = ( np.clip(aero_props.C_tau_corr, -2, 2) / (4 * np.maximum(geom.mu_mesh, 0.1) ** 2 * tsr * (1 - aero_props.an) * np.cos(eff_yaw)) diff --git a/examples/example_02_rotor_distributions.py b/examples/example_02_rotor_distributions.py index 517ea21..98e976f 100644 --- a/examples/example_02_rotor_distributions.py +++ b/examples/example_02_rotor_distributions.py @@ -17,7 +17,7 @@ def plot_radial_distributions(sol: BEMSolution, save_to: Path): [ax.legend(loc="lower center") for ax in axes] - axes[-1].set_xlabel("Radial position, $\mu$ [-]") + axes[-1].set_xlabel("Radial position, $\\mu$ [-]") plt.xlim(0, 1) plt.savefig(save_to, dpi=300, bbox_inches="tight") diff --git a/examples/example_04_yaw_tilt_rotor_comparison.py b/examples/example_04_yaw_tilt_rotor_comparison.py index 5b39520..9a809bf 100644 --- a/examples/example_04_yaw_tilt_rotor_comparison.py +++ b/examples/example_04_yaw_tilt_rotor_comparison.py @@ -41,7 +41,7 @@ axes[i, j].set_title(f"r/R ={np.round(r_mesh[0], decimals=2)}") fig.legend( - [f"Yaw ${rounded_deg_misalignment}^\circ$", f"Tilt ${rounded_deg_misalignment}^\circ$", f"Yaw ${np.rad2deg(yaw)}^\circ$ and Tilt ${np.rad2deg(yaw)}^\circ$"], # labels + [f"Yaw ${rounded_deg_misalignment}^\\circ$", f"Tilt ${rounded_deg_misalignment}^\\circ$", f"Yaw ${np.rad2deg(yaw)}^\\circ$ and Tilt ${np.rad2deg(yaw)}^\\circ$"], # labels loc='lower center', ncol=3, bbox_to_anchor=(0.5, 0.05) diff --git a/examples/example_06_floris_integration.py b/examples/example_06_floris_integration.py index 455c23d..e65bf3a 100644 --- a/examples/example_06_floris_integration.py +++ b/examples/example_06_floris_integration.py @@ -110,10 +110,10 @@ pitches = np.deg2rad(pitch_interp(wind_speeds)) tsrs = tsr_interp(wind_speeds) yaws, tilts = np.zeros_like(pitches), np.zeros_like(pitches) -mit_sols_rotor_umm = [bem_rotor_umm(pitch=pitches[i], tsr=tsrs[i], yaw=yaws[i], tilt=tilts[i]) for i in range(len(pitches))] +mit_sols_rotor_umm = bem_rotor_umm(pitch=pitches, tsr=tsrs, yaw=yaws, tilt=tilts) mit_rotor_umm_end = time.time() -mit_Ct_rotor_umm = [sol.Ct() for sol in mit_sols_rotor_umm] -mit_Cp_rotor_umm = [sol.Cp() for sol in mit_sols_rotor_umm] +mit_Ct_rotor_umm = mit_sols_rotor_umm.Ct() +mit_Cp_rotor_umm = mit_sols_rotor_umm.Cp() print("MITRotor UMM-BEM Rotor-Averaged: " + str(mit_rotor_umm_end - mit_rotor_umm_start) + " seconds") # solve UMM-BEM though MITRotor - annulus averaged @@ -124,10 +124,10 @@ tiploss_model=NoTipLoss(), ) mit_annulus_umm_start = time.time() -mit_sols_annulus_umm = [bem_annulus_umm(pitch=pitches[i], tsr=tsrs[i], yaw=yaws[i], tilt=tilts[i]) for i in range(len(pitches))] +mit_sols_annulus_umm = bem_annulus_umm(pitch=pitches, tsr=tsrs, yaw=yaws, tilt=tilts) mit_annulus_umm_end = time.time() -mit_Ct_annulus_umm = [sol.Ct() for sol in mit_sols_annulus_umm] -mit_Cp_annulus_umm = [sol.Cp() for sol in mit_sols_annulus_umm] +mit_Ct_annulus_umm = mit_sols_annulus_umm.Ct() +mit_Cp_annulus_umm = mit_sols_annulus_umm.Cp() print("MITRotor UMM-BEM Annulus-Averaged: " + str(mit_annulus_umm_end - mit_annulus_umm_start) + " seconds") # solve UMM-BEM though MITRotor - sector averaged @@ -153,10 +153,10 @@ tiploss_model=NoTipLoss(), ) mit_annulus_umm_LUT_start = time.time() -mit_sols_annulus_umm_LUT = [bem_annulus_umm_LUT(pitch=pitches[i], tsr=tsrs[i], yaw=yaws[i], tilt=tilts[i]) for i in range(len(pitches))] +mit_sols_annulus_umm_LUT = bem_annulus_umm_LUT(pitch=pitches, tsr=tsrs, yaw=yaws, tilt=tilts) mit_annulus_umm_LUT_end = time.time() -mit_Ct_annulus_umm_LUT = [sol.Ct() for sol in mit_sols_annulus_umm_LUT] -mit_Cp_annulus_umm_LUT = [sol.Cp() for sol in mit_sols_annulus_umm_LUT] +mit_Ct_annulus_umm_LUT = mit_sols_annulus_umm_LUT.Ct() +mit_Cp_annulus_umm_LUT = mit_sols_annulus_umm_LUT.Cp() print("MITRotor UMM-BEM LUT Annulus-Averaged: " + str(mit_annulus_umm_LUT_end - mit_annulus_umm_LUT_start) + " seconds") # solve FLORIS with UMM-BEM though MITRotor - rotor averaged @@ -374,4 +374,4 @@ loc="upper right", ) -plt.savefig(figdir / "example_6_IEA15mw_CT_CP.png", dpi=300) \ No newline at end of file +plt.savefig(figdir / "example_6_IEA15mw_CT_CP.png", dpi=300) diff --git a/examples/example_07_LUT_timing.py b/examples/example_07_LUT_timing.py new file mode 100644 index 0000000..988b814 --- /dev/null +++ b/examples/example_07_LUT_timing.py @@ -0,0 +1,128 @@ +import numpy as np +from pathlib import Path +from MITRotor.Momentum import UnifiedMomentumLUT, UnifiedMomentum +from MITRotor.TipLoss import NoTipLoss +from MITRotor import BEM, IEA15MW, BEMGeometry +import pandas as pd +import time + +# Floris imports +from floris import FlorisModel, TimeSeries +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory + +bem_rotor_umm = default_bem_factory() +bem_annulus_umm_LUT = BEM( + rotor=IEA15MW(), + momentum_model=UnifiedMomentumLUT(averaging="annulus", cache_fn = Path("cache")/ "lut.csv"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss(), +) +rotor_area = np.pi * bem_rotor_umm.rotor.R**2 + +bem_rotor_times = [] +bem_annulus_LUT_times = [] +wind_speeds_all = [] +bem_rotor_values = [] +bem_annulus_LUT_values = [] +ns = [5 * i for i in range(1, 21)] +for n in ns: + print(f"{n} wind speeds") + wind_speeds = np.linspace(5, 20, n) + wind_dirs = np.full_like(wind_speeds, 270.0) + turbulence_intensity = np.zeros_like(wind_speeds) + wind_speeds_all.extend( + np.squeeze(wind_speeds) + ) + + time_series = TimeSeries( + wind_speeds=wind_speeds, + wind_directions=wind_dirs, + turbulence_intensities=turbulence_intensity, + ) + + fmodel_rotor_umm = FlorisModel("defaults") + fmodel_rotor_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_rotor_umm.set_operation_model(MITRotorTurbine(bem_model = bem_rotor_umm)) # default bem_model uses rotor-averaging + floris_rotor_umm_start = time.time() + fmodel_rotor_umm.run() + floris_rotor_umm_end = time.time() + dt_rotor = floris_rotor_umm_end - floris_rotor_umm_start + print("FLORIS UMM-BEM Rotor-Averaged: " + str(dt_rotor) + " seconds") + bem_rotor_times.append(dt_rotor) + floris_Cp_rotor_umm = np.squeeze(fmodel_rotor_umm.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) + bem_rotor_values.extend( + np.squeeze(floris_Cp_rotor_umm) + ) + + # solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged + fmodel_annulus_umm_LUT = FlorisModel("defaults") + fmodel_annulus_umm_LUT.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_annulus_umm_LUT.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_umm_LUT)) # default bem_model uses rotor-averaging + floris_annulus_umm_LUT_start = time.time() + fmodel_annulus_umm_LUT.run() + floris_annulus_umm_LUT_end = time.time() + dt_annulus_LUT = floris_annulus_umm_LUT_end - floris_annulus_umm_LUT_start + print("FLORIS UMM-BEM LUT Annulus-Averaged: " + str(dt_annulus_LUT) + " seconds") + bem_annulus_LUT_times.append(dt_annulus_LUT) + floris_Cp_annulus_umm_LUT = np.squeeze(fmodel_annulus_umm_LUT.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) + bem_annulus_LUT_values.extend( + np.squeeze(floris_Cp_annulus_umm_LUT) + ) + +# make timing CSV +vectorized = True +rows = [] + +for n, dt in zip(ns, bem_rotor_times): + rows.append({ + "n_wind_speeds": n, + "runtime_seconds": dt, + "model": "rotor_umm", + "vectorized": vectorized + }) + +for n, dt in zip(ns, bem_annulus_LUT_times): + rows.append({ + "n_wind_speeds": n, + "runtime_seconds": dt, + "model": "annulus_lut", + "vectorized": vectorized + }) + +df = pd.DataFrame(rows) + +csv_path = Path("cache")/ "timing_results.csv" + +if csv_path.exists(): + df.to_csv(csv_path, mode="a", header=False, index=False) +else: + df.to_csv(csv_path, index=False) + +# make values CSV +rows = [] +# Rotor +for wind, val in zip(wind_speeds_all, bem_rotor_values): + rows.append({ + "wind_speed": wind, + "power": val, + "model": "rotor_umm", + "vectorized": vectorized + }) + +# Annulus LUT +for wind, val in zip(wind_speeds_all, bem_annulus_LUT_values): + rows.append({ + "wind_speed": wind, + "power": val, + "model": "annulus_lut", + "vectorized": vectorized + }) + +df = pd.DataFrame(rows) + +csv_path = Path("cache") / "value_results.csv" + +if csv_path.exists(): + df.to_csv(csv_path, mode="a", header=False, index=False) +else: + df.to_csv(csv_path, index=False) diff --git a/tests/test_bem.py b/tests/test_bem.py index b721efd..e58e7f4 100644 --- a/tests/test_bem.py +++ b/tests/test_bem.py @@ -1,4 +1,4 @@ -from MITRotor import BEM, IEA15MW, UnifiedMomentum, BEMGeometry +from MITRotor import BEM, IEA15MW, UnifiedMomentum, UnifiedMomentumLUT, BEMGeometry from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw import numpy as np from pytest import approx @@ -6,7 +6,6 @@ def test_IEA15MW(): IEA15MW() - def test_BEM_initialise(): rotor = IEA15MW() BEM(rotor=rotor) @@ -102,4 +101,72 @@ def test_model_yaw_tilt_rotor_phase(): # tilt and yaw should be offset by 90 degrees assert np.isclose(np.abs(theta_mesh[yaw_max_idx] - theta_mesh[tilt_max_idx]), np.pi / 2, atol = deg_atol) # yaw and evenly split yaw/tilt should be offset by 45 degrees - assert np.isclose(np.abs(theta_mesh[yaw_max_idx] - theta_mesh[yaw_and_tilt_max_idx]), np.pi / 4, atol = deg_atol) \ No newline at end of file + assert np.isclose(np.abs(theta_mesh[yaw_max_idx] - theta_mesh[yaw_and_tilt_max_idx]), np.pi / 4, atol = deg_atol) + +def _expected_shape(grid, Np, Nr, Ntheta): + if grid == "rotor": + return () if Np == 0 else (Np,) + elif grid == "annulus": + return (Nr,) if Np == 0 else (Np, Nr) + elif grid == "sector": + return (Nr, Ntheta) if Np == 0 else (Np, Nr, Ntheta) + else: + raise ValueError(grid) + + +def test_BEM_dimensionality(): + Nr, Ntheta = 20, 40 + rotor = IEA15MW() + + bems = [ + BEM(rotor=rotor, + momentum_model=UnifiedMomentum(averaging="rotor"), + geometry=BEMGeometry(Nr=Nr, Ntheta=Ntheta)), + + BEM(rotor=rotor, + momentum_model=UnifiedMomentumLUT(averaging="annulus"), + geometry=BEMGeometry(Nr=Nr, Ntheta=Ntheta)), + + BEM(rotor=rotor, + momentum_model=UnifiedMomentumLUT(averaging="sector"), + geometry=BEMGeometry(Nr=Nr, Ntheta=Ntheta)), + ] + + # --- inputs --- + pitch_s, tsr_s, yaw_s, tilt_s = 0.0, 7.0, 0.0, 0.0 + + pitch_v = np.array([0.0, 0.1, 0.2]) + tsr_v = np.array([6.0, 7.0, 8.0]) + yaw_v = np.array([0.0, 0.1, 0.2]) + tilt_v = np.array([0.0, -0.1, -0.2]) + + cases = [ + (pitch_s, tsr_s, yaw_s, tilt_s, 0), + (pitch_v, tsr_v, yaw_v, tilt_v, 3), + ] + + fields = ["Cp", "Cp_corr", "Ct", "a", "aoa"] + + for pitch, tsr, yaw, tilt, Np in cases: + for bem in bems: + sol = bem(pitch, tsr, yaw=yaw, tilt=tilt) + + # ========================= + # 1. u4, w4 dimensionality + # ========================= + u4 = np.asarray(sol.u4) + w4 = np.asarray(sol.w4) + + expected = () if Np == 0 else (Np,) + assert u4.shape == expected + assert w4.shape == expected + + # ========================= + # 2. Shape checks for fields + # ========================= + for grid in ["rotor", "annulus", "sector"]: + expected_shape = _expected_shape(grid, Np, Nr, Ntheta) + + for name in fields: + val = np.asarray(getattr(sol, name)(grid=grid)) + assert val.shape == expected_shape, f"{name}, {grid}" From 467cf2c4e43851838217de9c026153de33a64b53 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Mon, 1 Jun 2026 13:32:11 -0400 Subject: [PATCH 20/50] Add in ROSCO interface --- .gitignore | 3 +- MITRotor/BEMSolver.py | 7 + MITRotor/FlorisInterface/FlorisInterface.py | 8 +- MITRotor/FlorisInterface/ROSCOInterface.py | 146 + MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml | 62 + MITRotor/RotorDefinition.py | 11 + examples/example_08_floris_rosco.py | 83 + poetry.lock | 2677 ++++++++++++----- pyproject.toml | 3 +- 9 files changed, 2159 insertions(+), 841 deletions(-) create mode 100644 MITRotor/FlorisInterface/ROSCOInterface.py create mode 100644 MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml create mode 100644 examples/example_08_floris_rosco.py diff --git a/.gitignore b/.gitignore index 6984350..35206bb 100644 --- a/.gitignore +++ b/.gitignore @@ -195,4 +195,5 @@ pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python -.DS_Store \ No newline at end of file +.DS_Store +examples/Tune_Cases/ \ No newline at end of file diff --git a/MITRotor/BEMSolver.py b/MITRotor/BEMSolver.py index 7576268..fcd7ac1 100644 --- a/MITRotor/BEMSolver.py +++ b/MITRotor/BEMSolver.py @@ -127,6 +127,13 @@ def Ctprime(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): eff_yaw = calc_eff_yaw(self.yaw, self.tilt) Ctprime = self.Ct(grid="sector") / ((1 - self.a(grid="sector")) ** 2 * np.cos(eff_yaw) ** 2) return average(self.geom, Ctprime, grid=grid) + + # TODO: make sure that this is correct!! Check with np.isclose(Cp, tsr * Cq) + def Cq(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): + mu = np.asarray(self.geom.mu_mesh) + Ctau = self.Ctau_uncorr(grid="sector") + dCq = mu * Ctau + return average(self.geom, dCq, grid=grid) @adaptivefixedpointiteration(max_iter=500, relaxations=[0.25, 0.5, 0.96]) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 50c2646..22baaad 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -53,8 +53,10 @@ class MITRotorTurbine(BaseOperationModel): Args: bem_model (BEM): optional BEM model as defined in MITRotor, defaults to IEA15MW with UMM momentum model - pitch_csv (str): optional path to pitch trajectory based on wind speed, defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) - tsr_csv (str)): optional path to tsr trajectory based on wind speed, defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) + pitch_interp (interp1d): optional 1D interpolator for pitch trajectory based on wind speed, + defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) + tsr_interp (interp1d): optional 1D interpolator for tsr trajectory based on wind speed, + defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) Methods: power @@ -109,7 +111,7 @@ def _update_solution(self, # calculate rotor area rotor_area = np.pi * self.bem_model.rotor.R**2 - # get setpoints + # get setpoints yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) pitch = np.deg2rad(self.pitch_interp(rotor_average_velocities)) tsr = self.tsr_interp(rotor_average_velocities) diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py new file mode 100644 index 0000000..bc4be55 --- /dev/null +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -0,0 +1,146 @@ +import numpy as np +from scipy.interpolate import interp1d + +from rosco.toolbox import controller as ROSCO_controller +from rosco.toolbox import turbine as ROSCO_turbine +from rosco.toolbox.inputs.validation import load_rosco_yaml + +def load_from_mitrotor( + turbine, bem, refine_cp_surface=False, + TurbineName = "IEA15MW", GenEff = 95.756, generator_inertia = 1836784, +): + ''' + Loads rotor performance information by running MITRotor aerodynamic analysis. + + Based on ROSCO function load_from_ccblade: + https://github.com/NatLabRockies/ROSCO/blob/main/rosco/toolbox/turbine.py#L272 + + Args: + turbine (rosco.toolbox.turbine.Turbine): ROSCO turbine object + bem (MITRotor.BEM): MITRotor BEM object + refine_cp_surface (boolean): if true then smooth cp surface, else false + TurbineName (string): string turbine name; default to "IEA15MW" + GenEff (float): generator efficiency (0-100); defaults to IEA15MW value 95.756 + generator_inertia (float): generator_inertia; defaults to IEA15MW value 1836784 [kg m^2] + + Returns: turbine with new fields needed for ROSCO controller, including Ct, Cp, and Cq surfaces + ''' + turbine.TurbineName = TurbineName + turbine.rotor_performance_filename = 'Cp_Ct_Cq.txt' + + (tower_height, gearbox_efficiency, gearbox_ratio, air_density) = bem.rotor.rosco_values + turbine.TowerHt = tower_height + turbine.GBoxEff = gearbox_efficiency + turbine.Ng = gearbox_ratio + turbine.rho = air_density + + turbine.GenEff = GenEff + turbine.generator_inertia = generator_inertia + + turbine.yaw = 0.0 + turbine.rotor_radius = bem.rotor.R + turbine.J = turbine.rotor_inertia + turbine.generator_inertia * turbine.Ng**2 + turbine.rated_torque = turbine.rated_power/(turbine.GenEff/100*turbine.rated_rotor_speed*turbine.Ng) + + # Generate the look-up tables, mesh the grid and flatten the arrays for cc_rotor aerodynamic analysis + TSR_initial = np.arange(0.5, 25., 0.5) + pitch_initial = np.arange(0.0, 31., 1.0) + pitch_initial_rad = np.deg2rad(pitch_initial) + + tsr_mesh, pitch_rad_mesh = np.meshgrid(TSR_initial, pitch_initial_rad) + + tsr_flat = tsr_mesh.ravel() + pitch_rad_flat = pitch_rad_mesh.ravel() + + # Get values from MITRotor + print('Running MITRotor aerodynamic analysis, this may take a minute...') + + mit_sols = bem( + pitch_rad_flat, + tsr_flat, + yaw=np.zeros_like(tsr_flat), + tilt=np.zeros_like(tsr_flat), + ) + + print('MITRotor aerodynamic analysis run successfully.') + + # Reshape directly into lookup tables + n_pitch = len(pitch_initial_rad) + n_tsr = len(TSR_initial) + + Cp_table = mit_sols.Cp().reshape(n_pitch, n_tsr).T + Ct_table = mit_sols.Ct().reshape(n_pitch, n_tsr).T + Cq_table = mit_sols.Cq().reshape(n_pitch, n_tsr).T + + # Store necessary metrics for analysis + turbine.pitch_initial_rad = pitch_initial_rad + turbine.TSR_initial = TSR_initial + + turbine.Cp_table = Cp_table + turbine.Ct_table = Ct_table + turbine.Cq_table = Cq_table + + turbine.Cp = ROSCO_turbine.RotorPerformance(turbine.Cp_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) + turbine.Ct = ROSCO_turbine.RotorPerformance(turbine.Ct_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) + turbine.Cq = ROSCO_turbine.RotorPerformance(turbine.Cq_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) + return turbine + +def get_rosco_control_interps(rosco_yaml, bem, TurbineName = None, generator_inertia = None, GenEff = None): + """ + Creates pitch and tsr 1D interpolators using ROSCO controller tuning. + + Args: + rosco_yaml (string): yaml file that defineds turbine and control parameters; + [see MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml for example] + bem (MITRotor.BEM): MITRotor BEM object + TurbineName (string): string turbine name; default to "IEA15MW" + GenEff (float): generator efficiency (0-100); defaults to IEA15MW value 95.756 + generator_inertia (float): generator_inertia; defaults to IEA15MW value 1836784 [kg m^2] + + Returns: + pitch_interp (string): 1D pitch interpolator from wind speed tuned with ROSCO control paramters + tsr_interp (string): 1D tsr interpolator from wind speed tuned with ROSCO control paramters + """ + # load ROSCO inputs + inps = load_rosco_yaml(rosco_yaml) + turbine_params = inps['turbine_params'] + controller_params = inps['controller_params'] + + # make turbine + turbine = ROSCO_turbine.Turbine(turbine_params) + turbine = load_from_mitrotor( + turbine, bem, + TurbineName = TurbineName, generator_inertia = generator_inertia, GenEff = GenEff, + ) + + # make controller + controller = ROSCO_controller.Controller(controller_params) + controller.tune_controller(turbine) + + # get interpolators + pitch_interp = rosco_pitch_interp(controller) + tsr_interp = rosco_tsr_interp(controller) + + return pitch_interp, tsr_interp + +def rosco_pitch_interp(controller): + """ + Return 1D pitch interpolator from tuned ROSCO controller + + Args: + controller (rosco.toolbox.controller.Controller) + """ + wind_table = controller.v + pitch_table = np.maximum(controller.pitch_op, controller.ps_min_bld_pitch) + return interp1d(wind_table, pitch_table, kind="linear", fill_value="extrapolate", bounds_error=False) + +def rosco_tsr_interp(controller): + """ + Return 1D tsr interpolator from tuned ROSCO controller + + Args: + controller (rosco.toolbox.controller.Controller) + """ + wind_table = controller.v + tsr_table = controller.TSR_op + return interp1d(wind_table, tsr_table, kind="linear", fill_value="extrapolate", bounds_error=False) diff --git a/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml new file mode 100644 index 0000000..8046f29 --- /dev/null +++ b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml @@ -0,0 +1,62 @@ +# --------------------- ROSCO controller tuning input file ------------------- + # Written for use with ROSCO_Toolbox tuning procedures + # Turbine: IEA 15MW Reference Wind Turbine + # NOTE: The comments describing inputs in this file are not maintained. + # The most up-to-date descriptions can be found in the ROSCO documentation: https://rosco.readthedocs.io/en/latest/source/toolbox_input.html +# ------------------------------ OpenFAST PATH DEFINITIONS ------------------------------ +path_params: + FAST_InputFile: 'IEA-15-240-RWT-UMaineSemi.fst' # Name of *.fst file + FAST_directory: '../Test_Cases/IEA-15-240-RWT/IEA-15-240-RWT-UMaineSemi' # Main OpenFAST model directory, where the *.fst lives + # Optional (but suggested...) + rotor_performance_filename: '../Test_Cases/IEA-15-240-RWT/IEA-15-240-RWT/Cp_Ct_Cq.IEA15MW.txt' + +# -------------------------------- TURBINE PARAMETERS ----------------------------------- +turbine_params: + rotor_inertia: 310619488. # Rotor inertia [kg m^2], {Available in Elastodyn .sum file} + rated_rotor_speed: 0.7916813478 # Rated rotor speed [rad/s] + v_min: 3. # Cut-in wind speed [m/s] + v_rated: 10.74 # Rated wind speed [m/s] + v_max: 25.0 # Cut-out wind speed [m/s], -- Does not need to be exact (JUST ASSUME FOR NOW) + max_pitch_rate: 0.0349 # Maximum blade pitch rate [rad/s] + max_torque_rate: 4500000. # Maximum torque rate [Nm/s], {~1/4 VS_RtTq/s} + rated_power: 15000000. # Rated Power [W] + bld_edgewise_freq: 4.0324 # Blade edgewise first natural frequency [rad/s] + bld_flapwise_freq: 3.4872 # Blade flapwise first natural frequency [rad/s] + TSR_operational: 9.0 + +#------------------------------- CONTROLLER PARAMETERS ---------------------------------- +controller_params: + # Controller flags + LoggingLevel: 2 # {0: write no debug files, 1: write standard output .dbg-file, 2: write standard output .dbg-file and complete avrSWAP-array .dbg2-file + F_LPFType: 2 # {1: first-order low-pass filter, 2: second-order low-pass filter}, [rad/s] (currently filters generator speed and pitch control signals) + F_NotchType: 0 # Notch on the measured generator speed {0: disable, 1: enable} + IPC_ControlMode: 0 # Turn Individual Pitch Control (IPC) for fatigue load reductions (pitch contribution) {0: off, 1: 1P reductions, 2: 1P+2P reductions} + VS_ControlMode: 2 # Generator torque control mode in above rated conditions {0: constant torque, 1: constant power, 2: TSR tracking PI control} + PC_ControlMode: 1 # Blade pitch control mode {0: No pitch, fix to fine pitch, 1: active PI blade pitch control} + Y_ControlMode: 0 # Yaw control mode {0: no yaw control, 1: yaw rate control, 2: yaw-by-IPC} + SS_Mode: 1 # Setpoint Smoother mode {0: no setpoint smoothing, 1: introduce setpoint smoothing} + WE_Mode: 2 # Wind speed estimator mode {0: One-second low pass filtered hub height wind speed, 1: Immersion and Invariance Estimator (Ortega et al.)} + PS_Mode: 3 # Pitch saturation mode {0: no pitch saturation, 1: peak shaving, 2: Cp-maximizing pitch saturation, 3: peak shaving and Cp-maximizing pitch saturation} + SD_Mode: 0 # Shutdown mode {0: no shutdown procedure, 1: pitch to max pitch at shutdown} + Fl_Mode: 2 # Floating specific feedback mode {0: no nacelle velocity feedback, 1: nacelle velocity feedback} + Flp_Mode: 0 # Flap control mode {0: no flap control, 1: steady state flap angle, 2: Proportional flap control} + PA_Mode: 2 # Pitch actuator mode {0 - not used, 1 - first order filter, 2 - second order filter} + # Controller parameters + # U_pc: [14] + zeta_pc: 1.0 # Pitch controller desired damping ratio [-] + omega_pc: 0.2 # Pitch controller desired natural frequency [rad/s] + zeta_vs: 0.85 # Torque controller desired damping ratio [-] + omega_vs: 0.12 # Torque controller desired natural frequency [rad/s] + twr_freq: 3.355 # for semi only! + ptfm_freq: 0.213 # for semi only! + # Optional - these can be defined, but do not need to be + min_pitch: 0.0 # Minimum pitch angle [rad], {default = 0 degrees} + vs_minspd: 0.523598775 # Minimum rotor speed [rad/s], {default = 0 rad/s} + ps_percent: 0.8 # Percent peak shaving [%, <= 1 ], {default = 80%} + PA_CornerFreq: 1.5708 # Pitch actuator natural frequency [rad/s] + PA_Damping: 0.707 # Pitch actuator natural frequency [rad/s] + rgn2k_factor: 0.85926 + + DISCON: + IPC_KI: [1.2e-11, 0] + diff --git a/MITRotor/RotorDefinition.py b/MITRotor/RotorDefinition.py index 4e8d487..e036705 100644 --- a/MITRotor/RotorDefinition.py +++ b/MITRotor/RotorDefinition.py @@ -105,6 +105,13 @@ def from_windio(cls, windio: dict): airfoil_func = BladeAirfoils.from_windio(windio, hub_radius, R) + # Needed for ROSCO Control + tower_height = np.max(windio["components"]["tower"]["outer_shape_bem"]["reference_axis"]["z"]["values"]) + gearbox_efficiency = windio["components"]["nacelle"]["drivetrain"]["gearbox_efficiency"] * 100 + gearbox_ratio = windio["components"]["nacelle"]["drivetrain"]["gear_ratio"] + air_density = windio["environment"]["air_density"] + rosco_values = (tower_height, gearbox_efficiency, gearbox_ratio, air_density) + return cls( twist_func, solidity_func, @@ -117,6 +124,7 @@ def from_windio(cls, windio: dict): tsr_target, hub_radius, name=name, + rosco_values = rosco_values ) def __init__( @@ -132,6 +140,7 @@ def __init__( tsr_target, hub_radius, name=None, + rosco_values = None, ): self.name = name self.N_blades = N_blades @@ -147,6 +156,8 @@ def __init__( self.solidity_func = solidity_func self.airfoil_func = airfoil_func + self.rosco_values = rosco_values + def twist(self, mu): return self.twist_func(mu) diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py new file mode 100644 index 0000000..4707ecb --- /dev/null +++ b/examples/example_08_floris_rosco.py @@ -0,0 +1,83 @@ +# Python modules +import matplotlib.pyplot as plt +import os +# ROSCO toolbox modules +from rosco.toolbox import controller as ROSCO_controller +from rosco.toolbox import turbine as ROSCO_turbine +from rosco.toolbox.utilities import write_DISCON +from rosco.toolbox.inputs.validation import load_rosco_yaml +from rosco.toolbox.utilities import write_rotor_performance + +def main(): + from MITRotor.Momentum import UnifiedMomentumLUT + from MITRotor import BEM, BEMGeometry, NREL5MW, IEA15MW, IEA10MW + from pathlib import Path + import pandas as pd + + # load CSVs + pitch_15 = pd.read_csv("examples/Tune_Cases/IEA15_pitch.csv") + tsr_15 = pd.read_csv("examples/Tune_Cases/IEA15_TSR.csv") + pitch_5 = pd.read_csv("examples/Tune_Cases/NLR5_pitch.csv") + tsr_5 = pd.read_csv("examples/Tune_Cases/NLR5_TSR.csv") + + # calcualte new + cache_dir = Path("cache") + cache_dir.mkdir(exist_ok=True, parents=True) + cache_file = cache_dir / "lut.csv" + + # TODO: right now we are using 2 input files that have some shared parameters... + Nr, Ntheta = 10, 20 + lut_model = UnifiedMomentumLUT( + cache_fn=cache_file, + regenerate=False, + LUT_Cts=np.linspace(-0.5,1.5,40), + LUT_yaws=np.linspace(0.0,20.1,20), + ) + # NLR 5MW + inps_5 = load_rosco_yaml("examples/Tune_Cases/NLR_5MW.yaml") + turbine_params_5 = inps_5['turbine_params'] + controller_params_5 = inps_5['controller_params'] + rotor_5 = NREL5MW() + lut_bem_5 = BEM(rotor=rotor_5, momentum_model=lut_model, geometry = BEMGeometry(Nr=Nr, Ntheta=Ntheta)) + turbine_5 = ROSCO_turbine.Turbine(turbine_params_5) + turbine_5 = load_from_mitrotor(turbine_5, lut_bem_5, generator_inertia=534.116, GenEff=94.4) + controller_5 = ROSCO_controller.Controller(controller_params_5) + controller_5.tune_controller(turbine_5) + + + # IEA 15MW + inps_15 = load_rosco_yaml("examples/Tune_Cases/IEA15MW.yaml") + turbine_params_15 = inps_15['turbine_params'] + controller_params_15 = inps_15['controller_params'] + rotor_15 = IEA15MW() + lut_bem_15 = BEM(rotor=rotor_15, momentum_model=lut_model, geometry = BEMGeometry(Nr=Nr, Ntheta=Ntheta)) + turbine_15 = ROSCO_turbine.Turbine(turbine_params_15) + turbine_15 = load_from_mitrotor(turbine_15, lut_bem_15) + controller_15 = ROSCO_controller.Controller(controller_params_15) + controller_15.tune_controller(turbine_15) + + + plt.figure() + plt.plot(pitch_5["x"], pitch_5["y"], label = "NLR 5MW (Abbas et al.)", linestyle = "dashed") + plt.plot(pitch_15["x"], pitch_15["y"], label = "IEA 15MW (Abbas et al.)", linestyle = "dashed") + plt.plot(controller_5.v, np.rad2deg(np.maximum(controller_5.pitch_op, controller_5.ps_min_bld_pitch)), label='NLR 5MW (Generated)') + plt.plot(controller_15.v, np.rad2deg(np.maximum(controller_15.pitch_op, controller_15.ps_min_bld_pitch)), label='IEA 15MW (Generated)') + plt.xlabel('Wind Speed (m/s)') + plt.ylabel('Pitch') + plt.legend() + plt.grid(True) + plt.show() + + plt.figure() + plt.plot(tsr_5["x"], tsr_5["y"], label = "NLR 5MW (Abbas et al.)", linestyle = "dashed") + plt.plot(tsr_15["x"], tsr_15["y"], label = "IEA 15MW (Abbas et al.)", linestyle = "dashed") + plt.plot(controller_5.v, controller_5.TSR_op, label='NLR 5MW (Generated)') + plt.plot(controller_15.v, controller_15.TSR_op, label='IEA 15MW (Generated)') + plt.xlabel('Wind Speed (m/s)') + plt.ylabel('TSR') + plt.legend() + plt.grid(True) + plt.show() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 2fb0d6a..8760fae 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "anyio" -version = "4.12.1" +version = "4.13.0" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c"}, - {file = "anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703"}, + {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, + {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, ] [package.dependencies] @@ -18,7 +18,7 @@ idna = ">=2.8" typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] -trio = ["trio (>=0.31.0) ; python_version < \"3.10\"", "trio (>=0.32.0) ; python_version >= \"3.10\""] +trio = ["trio (>=0.32.0)"] [[package]] name = "appnope" @@ -128,14 +128,14 @@ test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"] [[package]] name = "async-lru" -version = "2.2.0" +version = "2.3.0" description = "Simple LRU cache for asyncio" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "async_lru-2.2.0-py3-none-any.whl", hash = "sha256:e2c1cf731eba202b59c5feedaef14ffd9d02ad0037fcda64938699f2c380eafe"}, - {file = "async_lru-2.2.0.tar.gz", hash = "sha256:80abae2a237dbc6c60861d621619af39f0d920aea306de34cb992c879e01370c"}, + {file = "async_lru-2.3.0-py3-none-any.whl", hash = "sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315"}, + {file = "async_lru-2.3.0.tar.gz", hash = "sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6"}, ] [package.dependencies] @@ -143,14 +143,14 @@ typing_extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "attrs" -version = "25.4.0" +version = "26.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"}, - {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"}, + {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, + {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, ] [[package]] @@ -259,16 +259,138 @@ webencodings = "*" [package.extras] css = ["tinycss2 (>=1.1.0,<1.5)"] +[[package]] +name = "cachebox" +version = "5.2.3" +description = "The fastest memoizing and caching Python library written in Rust" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "cachebox-5.2.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c2c89720547271d36e10cad2c7302bbe11f46eb39eead0a2c321c2d371b8f8b6"}, + {file = "cachebox-5.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7f33d24e90dc8aa26762e25898c91a1223b66685420a28a3628fa2e006924f5"}, + {file = "cachebox-5.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56cb03ec6289a2ac5daf7422d755683324f02d821bfa796087100df2a7ebd5de"}, + {file = "cachebox-5.2.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71a71df463ba4c86bc843fa01c3a2a721033adefad888af28c6b65e1915a75c"}, + {file = "cachebox-5.2.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbe4655371d19fc9f4f5874312bcb6e5b5b6182989979ac33d93c34c8d10c012"}, + {file = "cachebox-5.2.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4974476d1779961df89d6e6f79e6103a1659289d3ee11c92adcb52e236a8aaeb"}, + {file = "cachebox-5.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad16d733219f4cab3eec6533af30ab7b9c919c6e3e22ad1ef4eb82629a62edef"}, + {file = "cachebox-5.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:12a9e0a93774ca2b3a9fe8a2a0d0812e399fac4af0fce6246a5bca1e7009b8fc"}, + {file = "cachebox-5.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:be89497a011eb7a638d13cc520244d77579c0f515b95bf759b3de0b90a015203"}, + {file = "cachebox-5.2.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:dd01fc0c1934cccb76493eb4b149a9232d299e5e0275f557adf875c3d25cec81"}, + {file = "cachebox-5.2.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a0dfd97b0968f8bd48c33098a03d10f797964559c3a437c84bf97a9973545714"}, + {file = "cachebox-5.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:223ccf7ac60f595def258e7bc74c0b1d6f43991c9cae6d06749c803d22786d99"}, + {file = "cachebox-5.2.3-cp310-cp310-win32.whl", hash = "sha256:745b805fdd99931c3ce1d87d2ee21ca3fb62cba6b4e1f674907af87aad73dce4"}, + {file = "cachebox-5.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:a87b19c0a3d8d665a9805b5b4afd64b40082395b70ebe2756131ed1edb0c8f02"}, + {file = "cachebox-5.2.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:996f49d04b234082530afcc650bdd00556afbebc19c6c0daaafb85950340cb3c"}, + {file = "cachebox-5.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23a3300ebbb526fa12ce6fa53699002f5fba6da23b4bbbaf8ba8b18a3f03e6b3"}, + {file = "cachebox-5.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79c63ee1589364caa04c018405e625d2e44e0bf9994f2715b2f322075d8c45b6"}, + {file = "cachebox-5.2.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ebd0f8d4ebc3943c1ddcbbdc54f1a8ddf95505c862ed5731319cebd1eb98ae41"}, + {file = "cachebox-5.2.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:569966efcc6309aa7d774443e3513cdbb8671efae0158138ba2ebb7d8cc9d8ed"}, + {file = "cachebox-5.2.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5774d06f0da37dd566239a4376d6ca8cf983d3e4c3228712ec22b4130f662f21"}, + {file = "cachebox-5.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae5bf8755bc66bcf42e7ca5c42d703a041a7aaad58f9a0c3be54d5b1cefd2641"}, + {file = "cachebox-5.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63f061cc6a5ca70bbce2e6be0588fe2fee00a93a1b0581b1086d54b10288cdb6"}, + {file = "cachebox-5.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:577c781f18b559f4dc9eea176c6aed008843ef4b8e045cf61bb519e09dccc9ef"}, + {file = "cachebox-5.2.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7f691e25572a3ddbb018e19d796f774713bd6b0f7ce9be2e71f6e18572de264a"}, + {file = "cachebox-5.2.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:33368adf86669c29b936fbae5d6219cf90aacd4b1db71dae2e23d584a8219cd6"}, + {file = "cachebox-5.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:38ce67b7b45713e49459a09411d07f82de04022c04aecde6202cd32f934c2b1f"}, + {file = "cachebox-5.2.3-cp311-cp311-win32.whl", hash = "sha256:a7cd2c81347063ab6c512d0f569aeb5f75fc2dfe686c8486258ffd08052324f4"}, + {file = "cachebox-5.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:7e45798d6b969794840bb302857946d710ecb32af78dfcb3ab40f4e68ee7fdaf"}, + {file = "cachebox-5.2.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:09c0340e9daa7b4530801e5a570cb0c1a1ad941a85d245d360020d3986d0e787"}, + {file = "cachebox-5.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3162758792626685ec34950eedd565d015b115d0ff0d751d2716031fc32d51b"}, + {file = "cachebox-5.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a189a780c3ccd7b9d157074ba6bf3e191e522b39abbdb590075111851f02d50d"}, + {file = "cachebox-5.2.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:410b67baa99d433644199b11289627f7ebba4ee5786f95ca9858f238afcee157"}, + {file = "cachebox-5.2.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f81474dc19d3865fa5e57263f834bc6bbc00e471a594fb9d934ed552732c02fd"}, + {file = "cachebox-5.2.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85ccd827193b3e3e887a88a16b88ef7ed174e7e65be515b5253322aa75e665c3"}, + {file = "cachebox-5.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a1e7d3cb8a5e7e68996a8619e3ef8771a124d14568c251f9e586eba88d759c1"}, + {file = "cachebox-5.2.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:adcedfcfcb933b21e7fdcfe560c79887bc8287abceab0586aa3730417dd0277d"}, + {file = "cachebox-5.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c7f0c72c51a3a9e7049ea6ff2a43cd3877ab7fee966eb65771a59621563b75e3"}, + {file = "cachebox-5.2.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c48c10e498d573511aafbd545570e7f43b40a7428dc282183bf5adc334d9e1a8"}, + {file = "cachebox-5.2.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2f1e086ab5ffd082a68bb63699d517655a59b06414927bfc84e01df91b81e34d"}, + {file = "cachebox-5.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:649d18399f13735bb82daa33800196f815529c49e967767c40ca221723e68afa"}, + {file = "cachebox-5.2.3-cp312-cp312-win32.whl", hash = "sha256:0a17aeb4e5b1c6ef1c3db8fc5186f9986e215ba5ea5a5d08baa45bcf55f261b2"}, + {file = "cachebox-5.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:cfd69114141ab362acaa2099e425a1b965cf7b021a539a4e953143d593930b74"}, + {file = "cachebox-5.2.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9527c5c70f8735f2d696331d8bcf77254f03b4dc8542046807823bd36ed4e8ba"}, + {file = "cachebox-5.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40ac878af00d5969862c1f6bc076de1e34ca248662fce6aecca1761f52e33e32"}, + {file = "cachebox-5.2.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5ff26bfd8f7e95b3becf6d5f65c25edaca50fa68078868648b70d79bcccc260"}, + {file = "cachebox-5.2.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82e7002dd343afeeba2fcf0e483131b342a27ec3bc34b2214dc617691bda40d6"}, + {file = "cachebox-5.2.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ccbdc54a6c4b5758408c1083bdfa217bd382894a8331c7d0a54b84ba0cf51e5b"}, + {file = "cachebox-5.2.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df5135a168f143d186b1cc3be0ca16b66446897ab5cedc03bd80bcc926fcd403"}, + {file = "cachebox-5.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10bedf96db8f9766cc956f9adcc623e604264e5d6fa2e255432f8c2ed7519143"}, + {file = "cachebox-5.2.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f22732d0d69bb84ad2dca7480bffdfd0430c647152d488936e152ecbbfee52fb"}, + {file = "cachebox-5.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:26ae0b68979204d360327f4c0725cfdc95cfc34ab73ab1a8f528e3bd2f6d023c"}, + {file = "cachebox-5.2.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:f3d628b816e28a6e7661d460e02dd5b421247cc2cd275814f80ea79621245fc4"}, + {file = "cachebox-5.2.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:64057caa6b741320655cd3c5997fe642dae5dbff571eb530e6f53e58272bb43b"}, + {file = "cachebox-5.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa325306084aa2dc0b21e07723d7700f4d43dece3732c7fdaf7a269dc5e35aa7"}, + {file = "cachebox-5.2.3-cp313-cp313-win32.whl", hash = "sha256:55003089d21c2f5515089c307be063b45558e884a4a1cc9593944374c89975c4"}, + {file = "cachebox-5.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:dcc5edb6ecf2b516e90b773d232360c5e4ed8fdcda038b19441da2ed9cf208ab"}, + {file = "cachebox-5.2.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a4b7559fa4994c4032dd07466c2041d57e055feb814762e1f73f4e8beef188d0"}, + {file = "cachebox-5.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f57afada3d9327adf87f3b5cf0094348c6fd49354ab2e9bd20b044648eb094ae"}, + {file = "cachebox-5.2.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8342ff350ce86f062492752d612e9f056ac5dc56375713d75c3bf6e83b4d18db"}, + {file = "cachebox-5.2.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:405f9cc8492fc9d953b5a6b9e2b661e99583755c6639ab8d09a287fdf336503c"}, + {file = "cachebox-5.2.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94aae393ec1d9b26565d346445bb6afa3963d2a0d3eb5e4188d0e510fab871a0"}, + {file = "cachebox-5.2.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8b0b575066fc09f6fae0d4bd30d6ff56584a6870cbe7d202916c5e0d725cfd4"}, + {file = "cachebox-5.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41e99c1240106d39b63ce7868a6cd8c9da9243fef08848b85d428164e0769fd2"}, + {file = "cachebox-5.2.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:432ca62b99f7eafc21af669d76c88c1b7377db179b89fb6fca3ea93b8f9fff19"}, + {file = "cachebox-5.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e51d9c59006b53447f806145406eb37a7fc3c25553d4fd24c3887f3b268d214e"}, + {file = "cachebox-5.2.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:5e48a405f699fb001b8af120a6e0b4a981277f84eb5dd66a1faa21e4b6fe9485"}, + {file = "cachebox-5.2.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8cbfc007ea78af61d75d7d26e5854df53dc5da6877d074afd4b4696c074f4ee7"}, + {file = "cachebox-5.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6a94d0da8133b3a0707ae11c9ea321f8fc37e3b5a14517019a05d632218b0f56"}, + {file = "cachebox-5.2.3-cp313-cp313t-win32.whl", hash = "sha256:5fee33549877c03c2494ec5359a57a7667f872fe8e296a7f39d3dfe08dd3914c"}, + {file = "cachebox-5.2.3-cp313-cp313t-win_amd64.whl", hash = "sha256:67548a05cd41fcc4f7af80a2f97f742fef3d436537ac2e1a1dce0fcba5d41190"}, + {file = "cachebox-5.2.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:37fa0891f0defee053c09f5f43f802f731e36e6e6ca055d7d174af07f77232ca"}, + {file = "cachebox-5.2.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dc6315902f2ef4afbf10bc8e08c54ff34de5ce124546b8e0016c9b0d327be21e"}, + {file = "cachebox-5.2.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7df1735ca778480d51b8232fed397ffe3935158f20d34fb1c5ed171b53d5a6e2"}, + {file = "cachebox-5.2.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e22451cde8f884051e941b21870e4fc91fcf58d0d8c285bb8964107e1f02445c"}, + {file = "cachebox-5.2.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dcbccf3015d9a42bcf41260fa5cc048a5bdb75aa10997d514d6c976117f30ee2"}, + {file = "cachebox-5.2.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:311eae5079e256cbbfafdc3dcff1714b6598a767f9c1ef8c3709e74ea0cc12b0"}, + {file = "cachebox-5.2.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f4d2a80a5cd3380739c67f7d89e596634f5897b8d5a4a3dc1598312cb077535"}, + {file = "cachebox-5.2.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3977515b727a5203f494c44c4566fb936c4b940351c01d3d8e7b5d104dff4f53"}, + {file = "cachebox-5.2.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c5be17dd5c4fabcfecd5bcf6d54f9c6fb719daed3ef01ac1c03a14af0e2b26c1"}, + {file = "cachebox-5.2.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:6d37334fc218fdaee31db8a4f938938716e7c3b1b4059e25de27c8447fc95fde"}, + {file = "cachebox-5.2.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:1e5f1b7e23411b748d919348c3b65db1f9f8927ab8f6f3acae19bd617543df2d"}, + {file = "cachebox-5.2.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e7b06a75a898b31fd73c4d8bf727a9b9f8b5b7738cccd0ab5e6fd2a9cf659d3c"}, + {file = "cachebox-5.2.3-cp314-cp314-win32.whl", hash = "sha256:3b798052719f09a2ce7bf9fa9452dc0a7d4dc53b50a2d3aba6ce6ebc12d39df7"}, + {file = "cachebox-5.2.3-cp314-cp314-win_amd64.whl", hash = "sha256:4afc8b8575e3228a42ad8d819de5fbbecc6bd0b521295966b00244be37ae3b9b"}, + {file = "cachebox-5.2.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:0e8a34b82be30d3d9fb7dfaf9a86ec2b3ab9bc264715909ef27fc3d3587324d2"}, + {file = "cachebox-5.2.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4d4e336aebf866463878ccd28a4d0ef4003ea216708cf4a02a7f198481b3af81"}, + {file = "cachebox-5.2.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b102fcdd97b0602bf5d6ba1a571bba3e3d6fa912b89fd768b0da5427408eab8"}, + {file = "cachebox-5.2.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:245a79fb2c5d3bff252f4263f76210ef3ad7c2ff9b0234859b26974830a80491"}, + {file = "cachebox-5.2.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd0e8dbd8fd4cf664c645c08f9e10508e133353756705c4a738e90a5406224b5"}, + {file = "cachebox-5.2.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdb74294bdc33e39e26606919a9b2229038d5fac0edb80c9056683c08584d4a9"}, + {file = "cachebox-5.2.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bba3e9a7f52fa196b434522f39675f3b32a076976ef2373ded6f1065e99f4d20"}, + {file = "cachebox-5.2.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abb21f0f937fb66528f1b9f1a04874d6aa503e78bbb26f4cf33bf67faddbdd68"}, + {file = "cachebox-5.2.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:dab6fd3189b0c746fb03e1915fd947aaca9112cedf26ef3a0c39383acf87d2e5"}, + {file = "cachebox-5.2.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b4e7d2935b9df11d3717f99c7237b6780f1f8c70e6a99b69b8430d89929ec825"}, + {file = "cachebox-5.2.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:611aa260fe1b2506330ff72f415e2cb4053c9c4e3776ac68fe2eedee0e1b91b1"}, + {file = "cachebox-5.2.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a424ffb8514a9cb49bacff7995b7c767625cb2239692bd6524245e8579e375cc"}, + {file = "cachebox-5.2.3-cp314-cp314t-win32.whl", hash = "sha256:83988dd8e9075ee837e8407e26db49a9944ae74924d5db57b477444d7d98622c"}, + {file = "cachebox-5.2.3-cp314-cp314t-win_amd64.whl", hash = "sha256:dbda6390fa5070a19157ae35ab8066d3fe468634e0e9e21452c68ce7999c7d0c"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c798cddfb780156db09d3d96ed5da4c2d5fc01dad4bc7b54db5b20c34f221926"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:c8f3de4afeb3fd721620be3d02f2338bcbc3fdbd464ca14e1c474088c9669db0"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b39022c258872185327acffa9ad42d6bdf42f37d006d35c825a684eb5fa98d40"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a0599fb85dcb6df9a86502435643fe90c793bbcd50b5d85217c70f2bc2e38fc"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3cdbe8f1b7716a44dc82ef3a6830a612260c7379478cfa80804632e2e6252b8e"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:783d1b9a0b3c77c43e7ae331b9d6561ad75827e16b2484e2a6cc289ec4d392ee"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c6476a2a842906fee782d92f8fbcb03ecfd22eecc39adb7fb5b047d7e1cf020"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:184bbcfa1370415b6d1f09e4fb74ab697dac8df09f522aa217a2fac65f973744"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f89df36b46f8f5e11c0c49701ec3cebddf51191f96afb7bb75c394faf3c1cbc8"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:fb0bdcd9e28686e3b91d5210c843542858f0f10de151181aee27a7978fe4992e"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:5196f0d2c2f99c92ddf0d2c37803ff90509d14a5df211b7754feb8b61ffd8740"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:73671850d8c3634ab217398c83715d3feb52589ec97bd8e2f4d22e472741ea48"}, + {file = "cachebox-5.2.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:70c718f6bb77e6ba142b9a055b81ce85412a0c0e5e82a154489b45e6f91d09ec"}, + {file = "cachebox-5.2.3.tar.gz", hash = "sha256:b1f68246685aa739bbbd2734befb1465363a1e1042407c154feadb065f17a099"}, +] + [[package]] name = "certifi" -version = "2026.2.25" +version = "2026.4.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" -groups = ["dev"] +groups = ["main", "dev"] files = [ - {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, - {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, + {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"}, + {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"}, ] [[package]] @@ -277,7 +399,7 @@ version = "2.0.0" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -364,143 +486,214 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] +markers = {main = "implementation_name == \"pypy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} +[[package]] +name = "cftime" +version = "1.6.5" +description = "Time-handling functionality from netcdf4-python" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "cftime-1.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ad81e8cb0eb873b33c3d1e22c6168163fdc64daa8f7aeb4da8092f272575f4d"}, + {file = "cftime-1.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12d95c6af852114a13301c5a61e41afdbd1542e72939c1083796f8418b9b8b0e"}, + {file = "cftime-1.6.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2659b7df700e27d9e3671f686ce474dfb5fc274966961edf996acc148dfa094a"}, + {file = "cftime-1.6.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:94cebdfcda6a985b8e69aed22d00d6b8aa1f421495adbdcff1d59b3e896d81e2"}, + {file = "cftime-1.6.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:179681b023349a2fe277ceccc89d4fc52c0dd105cb59b7187b5bc5d442875133"}, + {file = "cftime-1.6.5-cp310-cp310-win_amd64.whl", hash = "sha256:d8b9fdecb466879cfe8ca4472b229b6f8d0bb65e4ffd44266ae17484bac2cf38"}, + {file = "cftime-1.6.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:474e728f5a387299418f8d7cb9c52248dcd5d977b2a01de7ec06bba572e26b02"}, + {file = "cftime-1.6.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab9e80d4de815cac2e2d88a2335231254980e545d0196eb34ee8f7ed612645f1"}, + {file = "cftime-1.6.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ad24a563784e4795cb3d04bd985895b5db49ace2cbb71fcf1321fd80141f9a52"}, + {file = "cftime-1.6.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a3cda6fd12c7fb25eff40a6a857a2bf4d03e8cc71f80485d8ddc65ccbd80f16a"}, + {file = "cftime-1.6.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:28cda78d685397ba23d06273b9c916c3938d8d9e6872a537e76b8408a321369b"}, + {file = "cftime-1.6.5-cp311-cp311-win_amd64.whl", hash = "sha256:93ead088e3a216bdeb9368733a0ef89a7451dfc1d2de310c1c0366a56ad60dc8"}, + {file = "cftime-1.6.5-cp311-cp311-win_arm64.whl", hash = "sha256:3384d69a0a7f3d45bded21a8cbcce66c8ba06c13498eac26c2de41b1b9b6e890"}, + {file = "cftime-1.6.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:eef25caed5ebd003a38719bd3ff8847cd52ef2ea56c3ebdb2c9345ba131fc7c5"}, + {file = "cftime-1.6.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c87d2f3b949e45463e559233c69e6a9cf691b2b378c1f7556166adfabbd1c6b0"}, + {file = "cftime-1.6.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:82cb413973cc51b55642b3a1ca5b28db5b93a294edbef7dc049c074b478b4647"}, + {file = "cftime-1.6.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85ba8e7356d239cfe56ef7707ac30feaf67964642ac760a82e507ee3c5db4ac4"}, + {file = "cftime-1.6.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:456039af7907a3146689bb80bfd8edabd074c7f3b4eca61f91b9c2670addd7ad"}, + {file = "cftime-1.6.5-cp312-cp312-win_amd64.whl", hash = "sha256:da84534c43699960dc980a9a765c33433c5de1a719a4916748c2d0e97a071e44"}, + {file = "cftime-1.6.5-cp312-cp312-win_arm64.whl", hash = "sha256:c62cd8db9ea40131eea7d4523691c5d806d3265d31279e4a58574a42c28acd77"}, + {file = "cftime-1.6.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4aba66fd6497711a47c656f3a732c2d1755ad15f80e323c44a8716ebde39ddd5"}, + {file = "cftime-1.6.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:89e7cba699242366e67d6fb5aee579440e791063f92a93853610c91647167c0d"}, + {file = "cftime-1.6.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2f1eb43d7a7b919ec99aee709fb62ef87ef1cf0679829ef93d37cc1c725781e9"}, + {file = "cftime-1.6.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e02a1d80ffc33fe469c7db68aa24c4a87f01da0c0c621373e5edadc92964900b"}, + {file = "cftime-1.6.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18ab754805233cdd889614b2b3b86a642f6d51a57a1ec327c48053f3414f87d8"}, + {file = "cftime-1.6.5-cp313-cp313-win_amd64.whl", hash = "sha256:6c27add8f907f4a4cd400e89438f2ea33e2eb5072541a157a4d013b7dbe93f9c"}, + {file = "cftime-1.6.5-cp313-cp313-win_arm64.whl", hash = "sha256:31d1ff8f6bbd4ca209099d24459ec16dea4fb4c9ab740fbb66dd057ccbd9b1b9"}, + {file = "cftime-1.6.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c69ce3bdae6a322cbb44e9ebc20770d47748002fb9d68846a1e934f1bd5daf0b"}, + {file = "cftime-1.6.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e62e9f2943e014c5ef583245bf2e878398af131c97e64f8cd47c1d7baef5c4e2"}, + {file = "cftime-1.6.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7da5fdaa4360d8cb89b71b8ded9314f2246aa34581e8105c94ad58d6102d9e4f"}, + {file = "cftime-1.6.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bff865b4ea4304f2744a1ad2b8149b8328b321dd7a2b9746ef926d229bd7cd49"}, + {file = "cftime-1.6.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e552c5d1c8a58f25af7521e49237db7ca52ed2953e974fe9f7c4491e95fdd36c"}, + {file = "cftime-1.6.5-cp314-cp314-win_amd64.whl", hash = "sha256:e645b095dc50a38ac454b7e7f0742f639e7d7f6b108ad329358544a6ff8c9ba2"}, + {file = "cftime-1.6.5-cp314-cp314-win_arm64.whl", hash = "sha256:b9044d7ac82d3d8af189df1032fdc871bbd3f3dd41a6ec79edceb5029b71e6e0"}, + {file = "cftime-1.6.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9ef56460cb0576e1a9161e1428c9e1a633f809a23fa9d598f313748c1ae5064e"}, + {file = "cftime-1.6.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4f4873d38b10032f9f3111c547a1d485519ae64eee6a7a2d091f1f8b08e1ba50"}, + {file = "cftime-1.6.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ccce0f4c9d3f38dd948a117e578b50d0e0db11e2ca9435fb358fd524813e4b61"}, + {file = "cftime-1.6.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19cbfc5152fb0b34ce03acf9668229af388d7baa63a78f936239cb011ccbe6b1"}, + {file = "cftime-1.6.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4470cd5ef3c2514566f53efbcbb64dd924fa0584637d90285b2f983bd4ee7d97"}, + {file = "cftime-1.6.5-cp314-cp314t-win_arm64.whl", hash = "sha256:034c15a67144a0a5590ef150c99f844897618b148b87131ed34fda7072614662"}, + {file = "cftime-1.6.5.tar.gz", hash = "sha256:8225fed6b9b43fb87683ebab52130450fc1730011150d3092096a90e54d1e81e"}, +] + +[package.dependencies] +numpy = ">=1.21.2" + [[package]] name = "charset-normalizer" -version = "3.4.4" +version = "3.4.7" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["dev"] +groups = ["main", "dev"] files = [ - {file = "charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d"}, - {file = "charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016"}, - {file = "charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525"}, - {file = "charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14"}, - {file = "charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c"}, - {file = "charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-win32.whl", hash = "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa"}, - {file = "charset_normalizer-3.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-win32.whl", hash = "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966"}, - {file = "charset_normalizer-3.4.4-cp39-cp39-win_arm64.whl", hash = "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50"}, - {file = "charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f"}, - {file = "charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_armv7l.whl", hash = "sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-win32.whl", hash = "sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-win32.whl", hash = "sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c"}, + {file = "charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d"}, + {file = "charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5"}, ] [[package]] name = "click" -version = "8.3.1" +version = "8.4.0" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, - {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, + {file = "click-8.4.0-py3-none-any.whl", hash = "sha256:40c50b7c6c6adac2823d411041ec84f3f103f1b280d5e9ce0d7f998995832f81"}, + {file = "click-8.4.0.tar.gz", hash = "sha256:638f1338fe1235c8f4e008e4a8a254fb5c5fbdcbb40ece3c9142ebb78e792973"}, ] [package.dependencies] @@ -559,7 +752,7 @@ description = "Python library for calculating contours of 2D quadrilateral grids optional = false python-versions = ">=3.10" groups = ["main", "examples"] -markers = "python_version == \"3.10\"" +markers = "python_version < \"3.11\"" files = [ {file = "contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934"}, {file = "contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989"}, @@ -723,6 +916,28 @@ mypy = ["bokeh", "contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.17.0)", " test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] +[[package]] +name = "control" +version = "0.10.2" +description = "Python Control Systems Library" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "control-0.10.2-py3-none-any.whl", hash = "sha256:8f7b5c58f5ccd761a6c070e3dedceca4c53c7a9cf105fcc22caba7a67f99025a"}, + {file = "control-0.10.2.tar.gz", hash = "sha256:d0cf63f6cfb68a4c8e827c26c3744d129e9777fedc9a5d86ca4740548f23a98b"}, +] + +[package.dependencies] +matplotlib = ">=3.6" +numpy = ">=1.23" +scipy = ">=1.8" + +[package.extras] +cvxopt = ["cvxopt (>=1.2.0)"] +slycot = ["slycot (>=0.4.0)"] +test = ["numpydoc", "pytest", "pytest-timeout", "ruff"] + [[package]] name = "cycler" version = "0.12.1" @@ -781,16 +996,41 @@ files = [ [[package]] name = "decorator" -version = "5.2.1" +version = "5.3.1" description = "Decorators for Humans" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}, - {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}, + {file = "decorator-5.3.1-py3-none-any.whl", hash = "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c"}, + {file = "decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82"}, ] +[[package]] +name = "deepdiff" +version = "9.1.0" +description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "deepdiff-9.1.0-py3-none-any.whl", hash = "sha256:80c0460e1993b04f6f0ca79abf25548b129fd218478c4ebb08f80560f5d10610"}, + {file = "deepdiff-9.1.0.tar.gz", hash = "sha256:07e9e366fab4297755153c4eab795ad4ef3cbd0d51660e847f5751c6bd727687"}, +] + +[package.dependencies] +cachebox = ">=5.2,<6" +orderly-set = ">=5.5.0,<6" + +[package.extras] +cli = ["click (>=8.3.1,<8.4.0)", "pyyaml (>=6.0.3,<6.1.0)"] +coverage = ["coverage (>=7.13.5,<7.14.0)"] +dev = ["bump2version (>=1.0.1,<1.1.0)", "flit-core (==3.12.0)", "ipdb (>=0.13.13,<0.14.0)", "jsonpickle (>=4.1.1,<4.2.0)", "nox (==2026.2.9)", "numpy (>=2.2.0,<2.3.0) ; python_version < \"3.14\"", "numpy (>=2.4.3,<2.5.0) ; python_version >= \"3.14\"", "orjson (>=3.11.7,<3.12.0)", "pandas (>=2.2.0,<2.3.0) ; python_version < \"3.11\"", "pandas (>=3.0.1,<3.1.0) ; python_version >= \"3.11\"", "polars (>=1.39.3,<1.40.0)", "python-dateutil (>=2.9.0.post0,<2.10.0)", "pytz", "tomli (>=2.4.0,<2.5.0)", "tomli-w (>=1.2.0,<1.3.0)", "uuid6 (==2025.0.1)"] +docs = ["Sphinx (>=8.1.3,<8.2.0)", "furo (>=2024.8.6)", "sphinx-sitemap (>=2.9.0,<2.10.0)", "sphinxemoji (>=0.3.2,<0.4.0)"] +optimize = ["orjson"] +static = ["flake8 (>=7.3.0,<7.4.0)", "flake8-pyproject (>=1.2.4,<1.3.0)", "pydantic (>=2.12.5,<2.13.0)"] +test = ["pytest (>=9.0.3,<9.1.0)", "pytest-benchmark (>=5.2.3,<5.3.0)", "pytest-cov (>=7.1.0,<7.2.0)", "python-dotenv (>=1.2.2,<1.3.0)"] + [[package]] name = "defusedxml" version = "0.7.1" @@ -819,6 +1059,18 @@ files = [ graph = ["objgraph (>=1.7.2)"] profile = ["gprof2dot (>=2022.7.29)"] +[[package]] +name = "et-xmlfile" +version = "2.0.0" +description = "An implementation of lxml.xmlfile for the standard library" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"}, + {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"}, +] + [[package]] name = "exceptiongroup" version = "1.3.1" @@ -826,7 +1078,7 @@ description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" groups = ["dev"] -markers = "python_version == \"3.10\"" +markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, @@ -898,66 +1150,66 @@ docs = ["bokeh (>=3.7,<4.0)", "jupyter-book (>=1.0,<2.0)", "ruamel.yaml (>=0.18. type = "git" url = "https://github.com/misi9170/floris.git" reference = "feature/user-def-op-mod" -resolved_reference = "c21ebc167354ef1b768d12ce08eb2ae2613bb055" +resolved_reference = "ba521ed04c64234ad46fb35d66dadb0f9d6716ac" [[package]] name = "fonttools" -version = "4.61.1" +version = "4.63.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.10" groups = ["main", "examples"] files = [ - {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c7db70d57e5e1089a274cbb2b1fd635c9a24de809a231b154965d415d6c6d24"}, - {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5fe9fd43882620017add5eabb781ebfbc6998ee49b35bd7f8f79af1f9f99a958"}, - {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8db08051fc9e7d8bc622f2112511b8107d8f27cd89e2f64ec45e9825e8288da"}, - {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a76d4cb80f41ba94a6691264be76435e5f72f2cb3cab0b092a6212855f71c2f6"}, - {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a13fc8aeb24bad755eea8f7f9d409438eb94e82cf86b08fe77a03fbc8f6a96b1"}, - {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b846a1fcf8beadeb9ea4f44ec5bdde393e2f1569e17d700bfc49cd69bde75881"}, - {file = "fonttools-4.61.1-cp310-cp310-win32.whl", hash = "sha256:78a7d3ab09dc47ac1a363a493e6112d8cabed7ba7caad5f54dbe2f08676d1b47"}, - {file = "fonttools-4.61.1-cp310-cp310-win_amd64.whl", hash = "sha256:eff1ac3cc66c2ac7cda1e64b4e2f3ffef474b7335f92fc3833fc632d595fcee6"}, - {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6604b735bb12fef8e0efd5578c9fb5d3d8532d5001ea13a19cddf295673ee09"}, - {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ce02f38a754f207f2f06557523cd39a06438ba3aafc0639c477ac409fc64e37"}, - {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77efb033d8d7ff233385f30c62c7c79271c8885d5c9657d967ede124671bbdfb"}, - {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:75c1a6dfac6abd407634420c93864a1e274ebc1c7531346d9254c0d8f6ca00f9"}, - {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0de30bfe7745c0d1ffa2b0b7048fb7123ad0d71107e10ee090fa0b16b9452e87"}, - {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58b0ee0ab5b1fc9921eccfe11d1435added19d6494dde14e323f25ad2bc30c56"}, - {file = "fonttools-4.61.1-cp311-cp311-win32.whl", hash = "sha256:f79b168428351d11e10c5aeb61a74e1851ec221081299f4cf56036a95431c43a"}, - {file = "fonttools-4.61.1-cp311-cp311-win_amd64.whl", hash = "sha256:fe2efccb324948a11dd09d22136fe2ac8a97d6c1347cf0b58a911dcd529f66b7"}, - {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e"}, - {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2"}, - {file = "fonttools-4.61.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10d88e55330e092940584774ee5e8a6971b01fc2f4d3466a1d6c158230880796"}, - {file = "fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d"}, - {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8"}, - {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0"}, - {file = "fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261"}, - {file = "fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9"}, - {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c"}, - {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e"}, - {file = "fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5"}, - {file = "fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd"}, - {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3"}, - {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d"}, - {file = "fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c"}, - {file = "fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b"}, - {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd"}, - {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e"}, - {file = "fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c"}, - {file = "fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75"}, - {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063"}, - {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2"}, - {file = "fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c"}, - {file = "fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c"}, - {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa"}, - {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91"}, - {file = "fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19"}, - {file = "fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba"}, - {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7"}, - {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118"}, - {file = "fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5"}, - {file = "fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b"}, - {file = "fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371"}, - {file = "fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69"}, + {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b"}, + {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94"}, + {file = "fonttools-4.63.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0425b277a59cff3d80ca42162a8de360f318438a2ac83570842a678d826d579"}, + {file = "fonttools-4.63.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d7e5c9973aa04c95650c96e5f5ad865fbf42d62079163ecfab1e01cbc2504c22"}, + {file = "fonttools-4.63.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cb014d58140a38135f16064c74c652ed57aa0b75cbf8bb59cac821f7edb5334e"}, + {file = "fonttools-4.63.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:032038247a96c1690f9f31e377c389383c902531b085aa4e4dabd6f57f870e69"}, + {file = "fonttools-4.63.0-cp310-cp310-win32.whl", hash = "sha256:a8b33a82979e0a6a34ff435cc81317be1f95ec1ebb7a3a2d1c8a6a54f02ae44e"}, + {file = "fonttools-4.63.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c18358a155d75034911c5ee397a5b44cd19dd325dbb8b35fb60bf421d6a72ac"}, + {file = "fonttools-4.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f"}, + {file = "fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9"}, + {file = "fonttools-4.63.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b"}, + {file = "fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18"}, + {file = "fonttools-4.63.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0"}, + {file = "fonttools-4.63.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007"}, + {file = "fonttools-4.63.0-cp311-cp311-win32.whl", hash = "sha256:afefc1ed0a59785a7fb06ea7e1678e849c193e1e387db783579bc7b3056fcfcb"}, + {file = "fonttools-4.63.0-cp311-cp311-win_amd64.whl", hash = "sha256:063e08bd17bd5a90127a14123de0d6a952dbc847695fd98b63c043d58057f90c"}, + {file = "fonttools-4.63.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02"}, + {file = "fonttools-4.63.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0"}, + {file = "fonttools-4.63.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af"}, + {file = "fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8"}, + {file = "fonttools-4.63.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b"}, + {file = "fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78"}, + {file = "fonttools-4.63.0-cp312-cp312-win32.whl", hash = "sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263"}, + {file = "fonttools-4.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272"}, + {file = "fonttools-4.63.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd"}, + {file = "fonttools-4.63.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59"}, + {file = "fonttools-4.63.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d"}, + {file = "fonttools-4.63.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68"}, + {file = "fonttools-4.63.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be"}, + {file = "fonttools-4.63.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27"}, + {file = "fonttools-4.63.0-cp313-cp313-win32.whl", hash = "sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380"}, + {file = "fonttools-4.63.0-cp313-cp313-win_amd64.whl", hash = "sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b"}, + {file = "fonttools-4.63.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745"}, + {file = "fonttools-4.63.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03"}, + {file = "fonttools-4.63.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49"}, + {file = "fonttools-4.63.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b"}, + {file = "fonttools-4.63.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6"}, + {file = "fonttools-4.63.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4"}, + {file = "fonttools-4.63.0-cp314-cp314-win32.whl", hash = "sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616"}, + {file = "fonttools-4.63.0-cp314-cp314-win_amd64.whl", hash = "sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5"}, + {file = "fonttools-4.63.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001"}, + {file = "fonttools-4.63.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e"}, + {file = "fonttools-4.63.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096"}, + {file = "fonttools-4.63.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f"}, + {file = "fonttools-4.63.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40"}, + {file = "fonttools-4.63.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196"}, + {file = "fonttools-4.63.0-cp314-cp314t-win32.whl", hash = "sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8"}, + {file = "fonttools-4.63.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419"}, + {file = "fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d"}, + {file = "fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0"}, ] [package.extras] @@ -1076,18 +1328,18 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "idna" -version = "3.11" +version = "3.15" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.8" -groups = ["dev"] +groups = ["main", "dev"] files = [ - {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, - {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, + {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, + {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, ] [package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "iniconfig" @@ -1137,14 +1389,14 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0,<9)", "pytest-async [[package]] name = "ipython" -version = "8.38.0" +version = "8.39.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "ipython-8.38.0-py3-none-any.whl", hash = "sha256:750162629d800ac65bb3b543a14e7a74b0e88063eac9b92124d4b2aa3f6d8e86"}, - {file = "ipython-8.38.0.tar.gz", hash = "sha256:9cfea8c903ce0867cc2f23199ed8545eb741f3a69420bfcf3743ad1cec856d39"}, + {file = "ipython-8.39.0-py3-none-any.whl", hash = "sha256:bb3c51c4fa8148ab1dea07a79584d1c854e234ea44aa1283bcb37bc75054651f"}, + {file = "ipython-8.39.0.tar.gz", hash = "sha256:4110ae96012c379b8b6db898a07e186c40a2a1ef5d57a7fa83166047d9da7624"}, ] [package.dependencies] @@ -1213,23 +1465,22 @@ arrow = ">=0.15.0" [[package]] name = "jedi" -version = "0.19.2" +version = "0.20.0" description = "An autocompletion tool for Python that can be used for text editors." optional = false -python-versions = ">=3.6" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, - {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, + {file = "jedi-0.20.0-py2.py3-none-any.whl", hash = "sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67"}, + {file = "jedi-0.20.0.tar.gz", hash = "sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011"}, ] [package.dependencies] -parso = ">=0.8.4,<0.9.0" +parso = ">=0.8.6,<0.9.0" [package.extras] -docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"] +dev = ["Django", "attrs", "colorama", "docopt", "flake8 (==7.1.2)", "pytest (<9.0.0)", "types-setuptools (==80.9.0.20250529)", "typing-extensions", "zuban (==0.7.0)"] +docs = ["Jinja2 (==3.1.6)", "MarkupSafe (==3.0.3)", "Pygments (==2.20.0)", "Sphinx (==9.1.0)", "alabaster (==1.0.0)", "babel (==2.18.0)", "certifi (==2026.4.22)", "charset-normalizer (==3.4.7)", "docutils (==0.22.4)", "idna (==3.13)", "imagesize (==2.0.0)", "iniconfig (==2.3.0)", "packaging (==26.2)", "pluggy (==1.6.0)", "pytest (==9.0.3)", "requests (==2.33.1)", "roman-numerals (==4.1.0)", "snowballstemmer (==3.0.1)", "sphinx-rtd-theme (==3.1.0)", "sphinxcontrib-applehelp (==2.0.0)", "sphinxcontrib-devhelp (==2.0.0)", "sphinxcontrib-htmlhelp (==2.1.0)", "sphinxcontrib-jquery (==4.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==2.0.0)", "sphinxcontrib-serializinghtml (==2.0.0)", "urllib3 (==2.6.3)"] [[package]] name = "jinja2" @@ -1251,26 +1502,41 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "json5" -version = "0.13.0" +version = "0.14.0" description = "A Python implementation of the JSON5 data format." optional = false python-versions = ">=3.8.0" groups = ["dev"] files = [ - {file = "json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc"}, - {file = "json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf"}, + {file = "json5-0.14.0-py3-none-any.whl", hash = "sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a"}, + {file = "json5-0.14.0.tar.gz", hash = "sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb"}, ] +[[package]] +name = "jsonmerge" +version = "1.9.2" +description = "Merge a series of JSON documents." +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "jsonmerge-1.9.2-py3-none-any.whl", hash = "sha256:cab93ee7763fb51a4a09bbdab2eacf499ffb208ab94247ae86acea3e0e823b05"}, + {file = "jsonmerge-1.9.2.tar.gz", hash = "sha256:c43757e0180b0e19b7ae4c130ad42a07cc580c31912f61f4823e8eaf2fa394a3"}, +] + +[package.dependencies] +jsonschema = ">2.4.0" + [[package]] name = "jsonpointer" -version = "3.0.0" -description = "Identify specific nodes in a JSON document (RFC 6901)" +version = "3.1.1" +description = "Identify specific nodes in a JSON document (RFC 6901) " optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, - {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, + {file = "jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca"}, + {file = "jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900"}, ] [[package]] @@ -1279,7 +1545,7 @@ version = "4.26.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.10" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, @@ -1310,7 +1576,7 @@ version = "2025.9.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, @@ -1410,14 +1676,14 @@ test = ["ipykernel", "pre-commit", "pytest (<9)", "pytest-cov", "pytest-timeout" [[package]] name = "jupyter-events" -version = "0.12.0" +version = "0.12.1" description = "Jupyter Event System library" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb"}, - {file = "jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b"}, + {file = "jupyter_events-0.12.1-py3-none-any.whl", hash = "sha256:c366585253f537a627da52fa7ca7410c5b5301fe893f511e7b077c2d93ec8bcf"}, + {file = "jupyter_events-0.12.1.tar.gz", hash = "sha256:faff25f77218335752f35f23c5fe6e4a392a7bd99a5939ccb9b8fbf594636cf3"}, ] [package.dependencies] @@ -1437,14 +1703,14 @@ test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "p [[package]] name = "jupyter-lsp" -version = "2.3.0" +version = "2.3.1" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "jupyter_lsp-2.3.0-py3-none-any.whl", hash = "sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f"}, - {file = "jupyter_lsp-2.3.0.tar.gz", hash = "sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245"}, + {file = "jupyter_lsp-2.3.1-py3-none-any.whl", hash = "sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81"}, + {file = "jupyter_lsp-2.3.1.tar.gz", hash = "sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6"}, ] [package.dependencies] @@ -1452,14 +1718,14 @@ jupyter_server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.17.0" +version = "2.18.2" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f"}, - {file = "jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5"}, + {file = "jupyter_server-2.18.2-py3-none-any.whl", hash = "sha256:fa5e46539ded65791838035a2b6001f13e54d5f64b8b3752eb1e91fdd641a5b8"}, + {file = "jupyter_server-2.18.2.tar.gz", hash = "sha256:06b4f40d8a7a00bb39d5216859c81374a0e7cfefe6d8a5a7facc5a5c37c679a7"}, ] [package.dependencies] @@ -1484,7 +1750,7 @@ traitlets = ">=5.6.0" websocket-client = ">=1.7" [package.extras] -docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] +docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx (<9.0)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] [[package]] @@ -1509,14 +1775,14 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.5.5" +version = "4.5.7" description = "JupyterLab computational environment" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "jupyterlab-4.5.5-py3-none-any.whl", hash = "sha256:a35694a40a8e7f2e82f387472af24e61b22adcce87b5a8ab97a5d9c486202a6d"}, - {file = "jupyterlab-4.5.5.tar.gz", hash = "sha256:eac620698c59eb810e1729909be418d9373d18137cac66637141abba613b3fda"}, + {file = "jupyterlab-4.5.7-py3-none-any.whl", hash = "sha256:fba4cb0e2c44a52859669d8c98b45de029d5e515f8407bf8534d2a8fc5f0964d"}, + {file = "jupyterlab-4.5.7.tar.gz", hash = "sha256:55a9822c4754da305f41e113452c68383e214dcf96de760146af89ce5d5117b0"}, ] [package.dependencies] @@ -1594,113 +1860,129 @@ files = [ [[package]] name = "kiwisolver" -version = "1.4.9" +version = "1.5.0" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.10" groups = ["main", "examples"] files = [ - {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b"}, - {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f"}, - {file = "kiwisolver-1.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84fd60810829c27ae375114cd379da1fa65e6918e1da405f356a775d49a62bcf"}, - {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78efa4c6e804ecdf727e580dbb9cba85624d2e1c6b5cb059c66290063bd99a9"}, - {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4efec7bcf21671db6a3294ff301d2fc861c31faa3c8740d1a94689234d1b415"}, - {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90f47e70293fc3688b71271100a1a5453aa9944a81d27ff779c108372cf5567b"}, - {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fdca1def57a2e88ef339de1737a1449d6dbf5fab184c54a1fca01d541317154"}, - {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cf554f21be770f5111a1690d42313e140355e687e05cf82cb23d0a721a64a48"}, - {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fc1795ac5cd0510207482c3d1d3ed781143383b8cfd36f5c645f3897ce066220"}, - {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ccd09f20ccdbbd341b21a67ab50a119b64a403b09288c27481575105283c1586"}, - {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:540c7c72324d864406a009d72f5d6856f49693db95d1fbb46cf86febef873634"}, - {file = "kiwisolver-1.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:ede8c6d533bc6601a47ad4046080d36b8fc99f81e6f1c17b0ac3c2dc91ac7611"}, - {file = "kiwisolver-1.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:7b4da0d01ac866a57dd61ac258c5607b4cd677f63abaec7b148354d2b2cdd536"}, - {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16"}, - {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089"}, - {file = "kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543"}, - {file = "kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61"}, - {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1"}, - {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872"}, - {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26"}, - {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028"}, - {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771"}, - {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a"}, - {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464"}, - {file = "kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2"}, - {file = "kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7"}, - {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999"}, - {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2"}, - {file = "kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14"}, - {file = "kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04"}, - {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752"}, - {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77"}, - {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198"}, - {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d"}, - {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab"}, - {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2"}, - {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145"}, - {file = "kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54"}, - {file = "kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60"}, - {file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8"}, - {file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2"}, - {file = "kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f"}, - {file = "kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098"}, - {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed"}, - {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525"}, - {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78"}, - {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b"}, - {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799"}, - {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3"}, - {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c"}, - {file = "kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d"}, - {file = "kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07"}, - {file = "kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c"}, - {file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386"}, - {file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552"}, - {file = "kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3"}, - {file = "kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58"}, - {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4"}, - {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df"}, - {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6"}, - {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5"}, - {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf"}, - {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5"}, - {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce"}, - {file = "kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7"}, - {file = "kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891"}, - {file = "kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32"}, - {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d1d9e582ad4d63062d34077a9a1e9f3c34088a2ec5135b1f7190c07cf366527"}, - {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:deed0c7258ceb4c44ad5ec7d9918f9f14fd05b2be86378d86cf50e63d1e7b771"}, - {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a590506f303f512dff6b7f75fd2fd18e16943efee932008fe7140e5fa91d80e"}, - {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e09c2279a4d01f099f52d5c4b3d9e208e91edcbd1a175c9662a8b16e000fece9"}, - {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c9e7cdf45d594ee04d5be1b24dd9d49f3d1590959b2271fb30b5ca2b262c00fb"}, - {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5"}, - {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa"}, - {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2"}, - {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f"}, - {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1"}, - {file = "kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d"}, + {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374"}, + {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd"}, + {file = "kiwisolver-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86e0287879f75621ae85197b0877ed2f8b7aa57b511c7331dce2eb6f4de7d476"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:62f59da443c4f4849f73a51a193b1d9d258dcad0c41bc4d1b8fb2bcc04bfeb22"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9190426b7aa26c5229501fa297b8d0653cfd3f5a36f7990c264e157cbf886b3b"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c8277104ded0a51e699c8c3aff63ce2c56d4ed5519a5f73e0fd7057f959a2b9e"}, + {file = "kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8f9baf6f0a6e7571c45c8863010b45e837c3ee1c2c77fcd6ef423be91b21fedb"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cff8e5383db4989311f99e814feeb90c4723eb4edca425b9d5d9c3fefcdd9537"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ebae99ed6764f2b5771c522477b311be313e8841d2e0376db2b10922daebbba4"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:d5cd5189fc2b6a538b75ae45433140c4823463918f7b1617c31e68b085c0022c"}, + {file = "kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f42c23db5d1521218a3276bb08666dcb662896a0be7347cba864eca45ff64ede"}, + {file = "kiwisolver-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:94eff26096eb5395136634622515b234ecb6c9979824c1f5004c6e3c3c85ccd2"}, + {file = "kiwisolver-1.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:dd952e03bfbb096cfe2dd35cd9e00f269969b67536cb4370994afc20ff2d0875"}, + {file = "kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c"}, + {file = "kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb"}, + {file = "kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc"}, + {file = "kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08"}, + {file = "kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4"}, + {file = "kiwisolver-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b"}, + {file = "kiwisolver-1.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac"}, + {file = "kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9"}, + {file = "kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588"}, + {file = "kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083"}, + {file = "kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314"}, + {file = "kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9"}, + {file = "kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384"}, + {file = "kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7"}, + {file = "kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09"}, + {file = "kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3"}, + {file = "kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8"}, + {file = "kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167"}, + {file = "kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0"}, + {file = "kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276"}, + {file = "kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2"}, + {file = "kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53"}, + {file = "kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615"}, + {file = "kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02"}, + {file = "kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a"}, + {file = "kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79"}, + {file = "kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796"}, + {file = "kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e"}, + {file = "kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681"}, + {file = "kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7"}, + {file = "kiwisolver-1.5.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:295d9ffe712caa9f8a3081de8d32fc60191b4b51c76f02f951fd8407253528f4"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:51e8c4084897de9f05898c2c2a39af6318044ae969d46ff7a34ed3f96274adca"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b83af57bdddef03c01a9138034c6ff03181a3028d9a1003b301eb1a55e161a3f"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf4679a3d71012a7c2bf360e5cd878fbd5e4fcac0896b56393dec239d81529ed"}, + {file = "kiwisolver-1.5.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:41024ed50e44ab1a60d3fe0a9d15a4ccc9f5f2b1d814ff283c8d01134d5b81bc"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16"}, + {file = "kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1"}, + {file = "kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a"}, ] [[package]] @@ -1723,103 +2005,103 @@ regex = ["regex"] [[package]] name = "librt" -version = "0.8.1" +version = "0.11.0" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc"}, - {file = "librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7"}, - {file = "librt-0.8.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6"}, - {file = "librt-0.8.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0"}, - {file = "librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b"}, - {file = "librt-0.8.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05"}, - {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891"}, - {file = "librt-0.8.1-cp310-cp310-win32.whl", hash = "sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7"}, - {file = "librt-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2"}, - {file = "librt-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd"}, - {file = "librt-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965"}, - {file = "librt-0.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da"}, - {file = "librt-0.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0"}, - {file = "librt-0.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e"}, - {file = "librt-0.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99"}, - {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe"}, - {file = "librt-0.8.1-cp311-cp311-win32.whl", hash = "sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb"}, - {file = "librt-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b"}, - {file = "librt-0.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9"}, - {file = "librt-0.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a"}, - {file = "librt-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9"}, - {file = "librt-0.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb"}, - {file = "librt-0.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d"}, - {file = "librt-0.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7"}, - {file = "librt-0.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921"}, - {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0"}, - {file = "librt-0.8.1-cp312-cp312-win32.whl", hash = "sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a"}, - {file = "librt-0.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444"}, - {file = "librt-0.8.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d"}, - {file = "librt-0.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35"}, - {file = "librt-0.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583"}, - {file = "librt-0.8.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c"}, - {file = "librt-0.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04"}, - {file = "librt-0.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363"}, - {file = "librt-0.8.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b"}, - {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d"}, - {file = "librt-0.8.1-cp313-cp313-win32.whl", hash = "sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a"}, - {file = "librt-0.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79"}, - {file = "librt-0.8.1-cp313-cp313-win_arm64.whl", hash = "sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0"}, - {file = "librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f"}, - {file = "librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c"}, - {file = "librt-0.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc"}, - {file = "librt-0.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c"}, - {file = "librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3"}, - {file = "librt-0.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071"}, - {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78"}, - {file = "librt-0.8.1-cp314-cp314-win32.whl", hash = "sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023"}, - {file = "librt-0.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730"}, - {file = "librt-0.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3"}, - {file = "librt-0.8.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1"}, - {file = "librt-0.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e"}, - {file = "librt-0.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382"}, - {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994"}, - {file = "librt-0.8.1-cp314-cp314t-win32.whl", hash = "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a"}, - {file = "librt-0.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4"}, - {file = "librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61"}, - {file = "librt-0.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac"}, - {file = "librt-0.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed"}, - {file = "librt-0.8.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd"}, - {file = "librt-0.8.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851"}, - {file = "librt-0.8.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128"}, - {file = "librt-0.8.1-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6"}, - {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed"}, - {file = "librt-0.8.1-cp39-cp39-win32.whl", hash = "sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc"}, - {file = "librt-0.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7"}, - {file = "librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73"}, + {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"}, + {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"}, + {file = "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"}, + {file = "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"}, + {file = "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"}, + {file = "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"}, + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"}, + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"}, + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"}, + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"}, + {file = "librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"}, + {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"}, + {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"}, + {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"}, + {file = "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"}, + {file = "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"}, + {file = "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"}, + {file = "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"}, + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"}, + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"}, + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"}, + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"}, + {file = "librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"}, + {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"}, + {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"}, + {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"}, + {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"}, + {file = "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"}, + {file = "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"}, + {file = "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"}, + {file = "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"}, + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"}, + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"}, + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"}, + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"}, + {file = "librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"}, + {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"}, + {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"}, + {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"}, + {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"}, + {file = "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"}, + {file = "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"}, + {file = "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"}, + {file = "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"}, + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"}, + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"}, + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"}, + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"}, + {file = "librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"}, + {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"}, + {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"}, + {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"}, + {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"}, + {file = "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"}, + {file = "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"}, + {file = "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"}, + {file = "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"}, + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"}, + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"}, + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"}, + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"}, + {file = "librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"}, + {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"}, + {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"}, + {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"}, + {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"}, + {file = "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"}, + {file = "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"}, + {file = "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"}, + {file = "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"}, + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"}, + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"}, + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"}, + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"}, + {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"}, + {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"}, + {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"}, + {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"}, + {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"}, + {file = "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"}, + {file = "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"}, + {file = "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"}, + {file = "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"}, + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"}, + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"}, + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"}, + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"}, + {file = "librt-0.11.0-cp39-cp39-win32.whl", hash = "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"}, + {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"}, + {file = "librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"}, ] [[package]] @@ -1921,69 +2203,84 @@ files = [ {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] +[[package]] +name = "marmot-agents" +version = "0.2.5" +description = "Agent based processs modeling." +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "marmot-agents-0.2.5.tar.gz", hash = "sha256:d0038c28928681b74352397a357f290da00c86a10c9626219b3ae36899faa915"}, + {file = "marmot_agents-0.2.5-py3-none-any.whl", hash = "sha256:f7678a830593222436396163fb0788d9d113bf84afb956b8854aad465830c2a6"}, +] + +[package.dependencies] +numpy = "*" + [[package]] name = "matplotlib" -version = "3.10.8" +version = "3.10.9" description = "Python plotting package" optional = false python-versions = ">=3.10" groups = ["main", "examples"] files = [ - {file = "matplotlib-3.10.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:00270d217d6b20d14b584c521f810d60c5c78406dc289859776550df837dcda7"}, - {file = "matplotlib-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b3c1cc42aa184b3f738cfa18c1c1d72fd496d85467a6cf7b807936d39aa656"}, - {file = "matplotlib-3.10.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee40c27c795bda6a5292e9cff9890189d32f7e3a0bf04e0e3c9430c4a00c37df"}, - {file = "matplotlib-3.10.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a48f2b74020919552ea25d222d5cc6af9ca3f4eb43a93e14d068457f545c2a17"}, - {file = "matplotlib-3.10.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f254d118d14a7f99d616271d6c3c27922c092dac11112670b157798b89bf4933"}, - {file = "matplotlib-3.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:f9b587c9c7274c1613a30afabf65a272114cd6cdbe67b3406f818c79d7ab2e2a"}, - {file = "matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160"}, - {file = "matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78"}, - {file = "matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4"}, - {file = "matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2"}, - {file = "matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6"}, - {file = "matplotlib-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9"}, - {file = "matplotlib-3.10.8-cp311-cp311-win_arm64.whl", hash = "sha256:bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2"}, - {file = "matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a"}, - {file = "matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58"}, - {file = "matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04"}, - {file = "matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f"}, - {file = "matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466"}, - {file = "matplotlib-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf"}, - {file = "matplotlib-3.10.8-cp312-cp312-win_arm64.whl", hash = "sha256:3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b"}, - {file = "matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6"}, - {file = "matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1"}, - {file = "matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486"}, - {file = "matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce"}, - {file = "matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6"}, - {file = "matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149"}, - {file = "matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645"}, - {file = "matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077"}, - {file = "matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22"}, - {file = "matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39"}, - {file = "matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565"}, - {file = "matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a"}, - {file = "matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958"}, - {file = "matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5"}, - {file = "matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f"}, - {file = "matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b"}, - {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d"}, - {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008"}, - {file = "matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c"}, - {file = "matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11"}, - {file = "matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8"}, - {file = "matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50"}, - {file = "matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908"}, - {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a"}, - {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1"}, - {file = "matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c"}, - {file = "matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b"}, - {file = "matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f"}, - {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f97aeb209c3d2511443f8797e3e5a569aebb040d4f8bc79aa3ee78a8fb9e3dd8"}, - {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fb061f596dad3a0f52b60dc6a5dec4a0c300dec41e058a7efe09256188d170b7"}, - {file = "matplotlib-3.10.8-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12d90df9183093fcd479f4172ac26b322b1248b15729cb57f42f71f24c7e37a3"}, - {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1"}, - {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a"}, - {file = "matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2"}, - {file = "matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3"}, + {file = "matplotlib-3.10.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77210dce9cb8153dffc967efaae990543392563d5a376d4dd8539bebcb0ed217"}, + {file = "matplotlib-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1e7698ac9868428e84d2c967424803b2472ff7167d9d6590d4204ed775343c3b"}, + {file = "matplotlib-3.10.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1aa972116abb4c9d201bf245620b433726cb6856f3bef6a78f776a00f5c92d37"}, + {file = "matplotlib-3.10.9-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae2f11957b27ce53497dd4d7b235c4d4f1faf383dfb39d0c5beb833bff883294"}, + {file = "matplotlib-3.10.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b049278ddce116aaa1c1377ebf58adea909132dfce0281cf7e3a1ea9fc2e2c65"}, + {file = "matplotlib-3.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:82834c3c292d24d3a8aae77cd2d20019de69d692a34a970e4fdb8d33e2ea3dda"}, + {file = "matplotlib-3.10.9-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:68cfdcede415f7c8f5577b03303dd94526cdb6d11036cecdc205e08733b2d2bb"}, + {file = "matplotlib-3.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfca0129678bd56379db26c52b5d77ed7de314c047492fbdc763aa7501710cfb"}, + {file = "matplotlib-3.10.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e436d155fa8a3399dc62683f8f5d0e2e50d25d0144a73edd73f82eec8f4abfb"}, + {file = "matplotlib-3.10.9-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56fc0bd271b00025c6edfdc7c2dcd247372c8e1544971d62e1dc7c17367e8bf9"}, + {file = "matplotlib-3.10.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5a6104ed666402ba5106d7f36e0e0cdca4e8d7fa4d39708ca88019e2835a2eb"}, + {file = "matplotlib-3.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:d730e984eddf56974c3e72b6129c7ca462ac38dc624338f4b0b23eb23ecba00f"}, + {file = "matplotlib-3.10.9-cp311-cp311-win_arm64.whl", hash = "sha256:51bf0ddbdc598e060d46c16b5590708f81a1624cefbaaf62f6a81bf9285b8c80"}, + {file = "matplotlib-3.10.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f0c3c28d9fbcc1fe7a03be236d73430cf6409c41fb2383a7ac52fe932b072cb1"}, + {file = "matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cb28c2bd769aa3e98322c6ab09854cbcc52ab69d2759d681bba3e327b2b320"}, + {file = "matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ae20801130378b82d647ff5047c07316295b68dc054ca6b3c13519d0ea624285"}, + {file = "matplotlib-3.10.9-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c63ebcd8b4b169eb2f5c200552ae6b8be8999a005b6b507ed76fb8d7d674fe2"}, + {file = "matplotlib-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d75d11c949914165976c621b2324f9ef162af7ebf4b057ddf95dd1dba7e5edcf"}, + {file = "matplotlib-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:d091f9d758b34aaaaa6331d13574bf01891d903b3dec59bfff458ef7551de5d6"}, + {file = "matplotlib-3.10.9-cp312-cp312-win_arm64.whl", hash = "sha256:10cc5ce06d10231c36f40e875f3c7e8050362a4ee8f0ee5d29a6b3277d57bb42"}, + {file = "matplotlib-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b580440f1ff81a0e34122051a3dfabb7e4b7f9e380629929bde0eff9af72165f"}, + {file = "matplotlib-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1b745c489cd1a77a0dc1120a05dc87af9798faebc913601feb8c73d89bf2d1e"}, + {file = "matplotlib-3.10.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8f3bcac1ca5ed000a6f4337d47ba67dfddf37ed6a46c15fd7f014997f7bf865f"}, + {file = "matplotlib-3.10.9-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a8d66a55def891c33147ba3ba9bfcabf0b526a43764c818acbb4525e5ed0838"}, + {file = "matplotlib-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d843374407c4017a6403b59c6c81606773d136f3259d5b6da3131bc814542cc2"}, + {file = "matplotlib-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:f4399f64b3e94cd500195490972ae1ee81170df1636fa15364d157d5bdd7b921"}, + {file = "matplotlib-3.10.9-cp313-cp313-win_arm64.whl", hash = "sha256:ba7b3b8ef09eab7df0e86e9ae086faa433efbfbdb46afcb3aa16aabf779469a8"}, + {file = "matplotlib-3.10.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:09218df8a93712bd6ea133e83a153c755448cf7868316c531cffcc43f69d1cc9"}, + {file = "matplotlib-3.10.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:82368699727bfb7b0182e1aa13082e3c08e092fa1a25d3e1fd92405bff96f6d4"}, + {file = "matplotlib-3.10.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3225f4e1edcb8c86c884ddf79ebe20ecd0a67d30188f279897554ccd8fded4dc"}, + {file = "matplotlib-3.10.9-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de2445a0c6690d21b7eb6ce071cebad6d40a2e9bdf10d039074a96ba19797b99"}, + {file = "matplotlib-3.10.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b2b9516251cb89ff618d757daec0e2ed1bf21248013844a853d87ef85ab3081d"}, + {file = "matplotlib-3.10.9-cp313-cp313t-win_amd64.whl", hash = "sha256:e9fae004b941b23ff2edcf1567a857ed77bafc8086ffa258190462328434faf8"}, + {file = "matplotlib-3.10.9-cp313-cp313t-win_arm64.whl", hash = "sha256:6b63d9c7c769b88ab81e10dc86e4e0607cf56817b9f9e6cf24b2a5f1693b8e38"}, + {file = "matplotlib-3.10.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:172db52c9e683f5d12eaf57f0f54834190e12581fe1cc2a19595a8f5acb4e77d"}, + {file = "matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97e35e8d39ccc85859095e01a53847432ba9a53ddf7986f7a54a11b73d0e143f"}, + {file = "matplotlib-3.10.9-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aba1615dabe83188e19d4f75a253c6a08423e04c1425e64039f800050a69de6b"}, + {file = "matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34cf8167e023ad956c15f36302911d5406bd99a9862c1a8499ea6f7c0e015dc2"}, + {file = "matplotlib-3.10.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59476c6d29d612b8e9bb6ce8c5b631be6ba8f9e3a2421f22a02b192c7dd28716"}, + {file = "matplotlib-3.10.9-cp314-cp314-win_amd64.whl", hash = "sha256:336b9acc64d309063126edcdaca00db9373af3c476bb94388fe9c5a53ad13e6f"}, + {file = "matplotlib-3.10.9-cp314-cp314-win_arm64.whl", hash = "sha256:2dc9477819ffd78ad12a20df1d9d6a6bd4fec6aaa9072681465fddca052f1456"}, + {file = "matplotlib-3.10.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:da4e09638420548f31c354032a6250e473c68e5a4e96899b4844cf39ddea23fe"}, + {file = "matplotlib-3.10.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:345f6f68ecc8da0ca56fad2ea08fde1a115eda530079eca185d50a7bc3e146c6"}, + {file = "matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4edcfbd8565339aa62f1cd4012f7180926fdbe71850f7b0d3c379c175cd6b66c"}, + {file = "matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6be157fe17fc37cb95ac1d7374cf717ce9259616edec911a78d9d26dae8522d4"}, + {file = "matplotlib-3.10.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4e42042d54db34fda4e95a7bd3e5789c2a995d2dad3eb8850232ee534092fbbf"}, + {file = "matplotlib-3.10.9-cp314-cp314t-win_amd64.whl", hash = "sha256:c27df8b3848f32a83d1767566595e43cfaa4460380974da06f4279a7ec143c39"}, + {file = "matplotlib-3.10.9-cp314-cp314t-win_arm64.whl", hash = "sha256:a49f1eadc84ca85fd72fa4e89e70e61bf86452df6f971af04b12c60761a0772c"}, + {file = "matplotlib-3.10.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1872fb212a05b729e649754a72d5da61d03e0554d76e80303b6f83d1d2c0552b"}, + {file = "matplotlib-3.10.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:985f2238880e2e69093f588f5fe2e46771747febf0649f3cf7f7b7480875317f"}, + {file = "matplotlib-3.10.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6640f75af2c6148293caa0a2b39dd806a492dd66c8a8b04035813e33d0fd2585"}, + {file = "matplotlib-3.10.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:42fb814efabe95c06c1994d8ab5a8385f43a249e23badd3ba931d4308e5bca20"}, + {file = "matplotlib-3.10.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f76e640a5268850bfda54b5131b1b1941cc685e42c5fa98ed9f2d64038308cba"}, + {file = "matplotlib-3.10.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3fc0364dfbe1d07f6d15c5ebd0c5bf89e126916e5a8667dd4a7a6e84c36653d4"}, + {file = "matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358"}, ] [package.dependencies] @@ -1998,41 +2295,64 @@ pyparsing = ">=3" python-dateutil = ">=2.7" [package.extras] -dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7)"] +dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7,<10)"] [[package]] name = "matplotlib-inline" -version = "0.2.1" +version = "0.2.2" description = "Inline Matplotlib backend for Jupyter" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76"}, - {file = "matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe"}, + {file = "matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6"}, + {file = "matplotlib_inline-0.2.2.tar.gz", hash = "sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79"}, ] [package.dependencies] traitlets = "*" [package.extras] -test = ["flake8", "nbdime", "nbval", "notebook", "pytest"] +test = ["flake8", "matplotlib", "nbdime", "nbval", "notebook", "pytest"] [[package]] name = "mistune" -version = "3.2.0" +version = "3.2.1" description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1"}, - {file = "mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a"}, + {file = "mistune-3.2.1-py3-none-any.whl", hash = "sha256:78cdb0ba5e938053ccf63651b352508d2efa9411dc8810bfb05f2dc5140c0048"}, + {file = "mistune-3.2.1.tar.gz", hash = "sha256:7c8e5501d38bac1582e067e46c8343f17d57ea1aaa735823f3aba1fd59c88a28"}, ] [package.dependencies] typing-extensions = {version = "*", markers = "python_version < \"3.11\""} +[[package]] +name = "moorpy" +version = "1.3.0" +description = "A design-oriented mooring system library for Python" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "moorpy-1.3.0-py3-none-any.whl", hash = "sha256:2a6bf0f9db32fd49624471aeb152925ede383c0414db853c47069d5b3cd55b12"}, + {file = "moorpy-1.3.0.tar.gz", hash = "sha256:ccef5e65a8a0f65be48e0fc39275918c318390937bf426c26a96d5fda0692256"}, +] + +[package.dependencies] +matplotlib = "*" +numpy = "*" +pyyaml = "*" +scipy = "*" + +[package.extras] +dev = ["pre-commit"] +docs = ["sphinx", "sphinx-rtd-theme"] +test = ["pytest", "pytest-cov", "pytest-xdist"] + [[package]] name = "multiprocess" version = "0.70.19" @@ -2064,64 +2384,71 @@ dill = ">=0.4.1" [[package]] name = "mypy" -version = "1.19.1" +version = "1.20.2" description = "Optional static typing for Python" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec"}, - {file = "mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b"}, - {file = "mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6"}, - {file = "mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74"}, - {file = "mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1"}, - {file = "mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac"}, - {file = "mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288"}, - {file = "mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab"}, - {file = "mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6"}, - {file = "mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331"}, - {file = "mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925"}, - {file = "mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042"}, - {file = "mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1"}, - {file = "mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e"}, - {file = "mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2"}, - {file = "mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8"}, - {file = "mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a"}, - {file = "mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13"}, - {file = "mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250"}, - {file = "mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b"}, - {file = "mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e"}, - {file = "mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef"}, - {file = "mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75"}, - {file = "mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd"}, - {file = "mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1"}, - {file = "mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718"}, - {file = "mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b"}, - {file = "mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045"}, - {file = "mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957"}, - {file = "mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f"}, - {file = "mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3"}, - {file = "mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a"}, - {file = "mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67"}, - {file = "mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e"}, - {file = "mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376"}, - {file = "mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24"}, - {file = "mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247"}, - {file = "mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba"}, + {file = "mypy-1.20.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cf5a4db6dca263010e2c7bff081c89383c72d187ba2cf4c44759aac970e2f0c4"}, + {file = "mypy-1.20.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b0e817b518bff7facd7f85ea05b643ad8bdcce684cf29784987b0a7c8e1f997"}, + {file = "mypy-1.20.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97d7b9a485b40f8ca425460e89bf1da2814625b2da627c0dcc6aa46c92631d14"}, + {file = "mypy-1.20.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e1c12f6d2db3d78b909b5f77513c11eb7f2dd2782b96a3ab6dffc7d44575c99"}, + {file = "mypy-1.20.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:89dce27e142d25ffbc154c1819383b69f2e9234dc4ed4766f42e0e8cb264ab5c"}, + {file = "mypy-1.20.2-cp310-cp310-win_amd64.whl", hash = "sha256:f376e37f9bf2a946872fc5fd1199c99310748e3c26c7a26683f13f8bdb756cbd"}, + {file = "mypy-1.20.2-cp310-cp310-win_arm64.whl", hash = "sha256:6e2b469efd811707bc530fd1effef0f5d6eebcb7fe376affae69025da4b979a2"}, + {file = "mypy-1.20.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4077797a273e56e8843d001e9dfe4ba10e33323d6ade647ff260e5cd97d9758c"}, + {file = "mypy-1.20.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cdecf62abcc4292500d7858aeae87a1f8f1150f4c4dd08fb0b336ee79b2a6df3"}, + {file = "mypy-1.20.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c566c3a88b6ece59b3d70f65bedef17304f48eb52ff040a6a18214e1917b3254"}, + {file = "mypy-1.20.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0deb80d062b2479f2c87ae568f89845afc71d11bc41b04179e58165fd9f31e98"}, + {file = "mypy-1.20.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bba9ad231e92a3e424b3e56b65aa17704993425bba97e302c832f9466bb85bac"}, + {file = "mypy-1.20.2-cp311-cp311-win_amd64.whl", hash = "sha256:baf593f2765fa3a6b1ef95807dbaa3d25b594f6a52adcc506a6b9cb115e1be67"}, + {file = "mypy-1.20.2-cp311-cp311-win_arm64.whl", hash = "sha256:20175a1c0f49863946ec20b7f63255768058ac4f07d2b9ded6a6b46cfb5a9100"}, + {file = "mypy-1.20.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4dbfcf869f6b0517f70cf0030ba6ea1d6645e132337a7d5204a18d8d5636c02b"}, + {file = "mypy-1.20.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b6481b228d072315b053210b01ac320e1be243dc17f9e5887ef167f23f5fae4"}, + {file = "mypy-1.20.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34397cdced6b90b836e38182076049fdb41424322e0b0728c946b0939ebdf9f6"}, + {file = "mypy-1.20.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5da6976f20cae27059ea8d0c86e7cef3de720e04c4bb9ee18e3690fdb792066"}, + {file = "mypy-1.20.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:56908d7e08318d39f85b1f0c6cfd47b0cac1a130da677630dac0de3e0623e102"}, + {file = "mypy-1.20.2-cp312-cp312-win_amd64.whl", hash = "sha256:d52ad8d78522da1d308789df651ee5379088e77c76cb1994858d40a426b343b9"}, + {file = "mypy-1.20.2-cp312-cp312-win_arm64.whl", hash = "sha256:785b08db19c9f214dc37d65f7c165d19a30fcecb48abfa30f31b01b5acaabb58"}, + {file = "mypy-1.20.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:edfbfca868cdd6bd8d974a60f8a3682f5565d3f5c99b327640cedd24c4264026"}, + {file = "mypy-1.20.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e2877a02380adfcdbc69071a0f74d6e9dbbf593c0dc9d174e1f223ffd5281943"}, + {file = "mypy-1.20.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7488448de6007cd5177c6cea0517ac33b4c0f5ee9b5e9f2be51ce75511a85517"}, + {file = "mypy-1.20.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb9c2fa06887e21d6a3a868762acb82aec34e2c6fd0174064f27c93ede68ad15"}, + {file = "mypy-1.20.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d56a78b646f2e3daa865bc70cd5ec5a46c50045801ca8ff17a0c43abc97e3ee"}, + {file = "mypy-1.20.2-cp313-cp313-win_amd64.whl", hash = "sha256:2a4102b03bb7481d9a91a6da8d174740c9c8c4401024684b9ca3b7cc5e49852f"}, + {file = "mypy-1.20.2-cp313-cp313-win_arm64.whl", hash = "sha256:a95a9248b0c6fd933a442c03c3b113c3b61320086b88e2c444676d3fd1ca3330"}, + {file = "mypy-1.20.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:419413398fe250aae057fd2fe50166b61077083c9b82754c341cf4fd73038f30"}, + {file = "mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e73c07f23009962885c197ccb9b41356a30cc0e5a1d0c2ea8fd8fb1362d7f924"}, + {file = "mypy-1.20.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c64e5973df366b747646fc98da921f9d6eba9716d57d1db94a83c026a08e0fb"}, + {file = "mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a65aa591af023864fd08a97da9974e919452cfe19cb146c8a5dc692626445dc"}, + {file = "mypy-1.20.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4fef51b01e638974a6e69885687e9bd40c8d1e09a6cd291cca0619625cf1f558"}, + {file = "mypy-1.20.2-cp314-cp314-win_amd64.whl", hash = "sha256:913485a03f1bcf5d279409a9d2b9ed565c151f61c09f29991e5faa14033da4c8"}, + {file = "mypy-1.20.2-cp314-cp314-win_arm64.whl", hash = "sha256:c3bae4f855d965b5453784300c12ffc63a548304ac7f99e55d4dc7c898673aa3"}, + {file = "mypy-1.20.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2de3dcea53babc1c3237a19002bc3d228ce1833278f093b8d619e06e7cc79609"}, + {file = "mypy-1.20.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:52b176444e2e5054dfcbcb8c75b0b719865c96247b37407184bbfca5c353f2c2"}, + {file = "mypy-1.20.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:688c3312e5dadb573a2c69c82af3a298d43ecf9e6d264e0f95df960b5f6ac19c"}, + {file = "mypy-1.20.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29752dbbf8cc53f89f6ac096d363314333045c257c9c75cbd189ca2de0455744"}, + {file = "mypy-1.20.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:803203d2b6ea644982c644895c2f78b28d0e208bba7b27d9b921e0ec5eb207c6"}, + {file = "mypy-1.20.2-cp314-cp314t-win_amd64.whl", hash = "sha256:9bcb8aa397ff0093c824182fd76a935a9ba7ad097fcbef80ae89bf6c1731d8ec"}, + {file = "mypy-1.20.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e061b58443f1736f8a37c48978d7ab581636d6ab03e3d4f99e3fa90463bb9382"}, + {file = "mypy-1.20.2-py3-none-any.whl", hash = "sha256:a94c5a76ab46c5e6257c7972b6c8cff0574201ca7dc05647e33e795d78680563"}, + {file = "mypy-1.20.2.tar.gz", hash = "sha256:e8222c26daaafd9e8626dec58ae36029f82585890589576f769a650dd20fd665"}, ] [package.dependencies] -librt = {version = ">=0.6.2", markers = "platform_python_implementation != \"PyPy\""} +librt = {version = ">=0.8.0", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" -pathspec = ">=0.9.0" +pathspec = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing_extensions = ">=4.6.0" +typing_extensions = {version = ">=4.6.0", markers = "python_version < \"3.15\""} [package.extras] dmypy = ["psutil (>=4.0)"] faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] +native-parser = ["ast-serialize (>=0.1.1,<1.0.0)"] reports = ["lxml"] [[package]] @@ -2161,14 +2488,14 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.17.0" +version = "7.17.1" description = "Convert Jupyter Notebooks (.ipynb files) to other formats." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "nbconvert-7.17.0-py3-none-any.whl", hash = "sha256:4f99a63b337b9a23504347afdab24a11faa7d86b405e5c8f9881cd313336d518"}, - {file = "nbconvert-7.17.0.tar.gz", hash = "sha256:1b2696f1b5be12309f6c7d707c24af604b87dfaf6d950794c7b07acab96dda78"}, + {file = "nbconvert-7.17.1-py3-none-any.whl", hash = "sha256:aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8"}, + {file = "nbconvert-7.17.1.tar.gz", hash = "sha256:34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2"}, ] [package.dependencies] @@ -2230,21 +2557,166 @@ files = [ {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] +[[package]] +name = "netcdf4" +version = "1.7.3" +description = "Provides an object-oriented python interface to the netCDF version 4 library" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "platform_system == \"Windows\" and platform_machine == \"ARM64\" and python_version < \"3.11\"" +files = [ + {file = "netcdf4-1.7.3-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:db761afd3a6b9482df018c4783e0bdf99141a41db1f14c68c89986effb182d57"}, + {file = "netcdf4-1.7.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:ad4c2d9b469248d83cbacb70ad9e7d3a6c0ba27febe839c90192147199745ba4"}, + {file = "netcdf4-1.7.3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6986d039717582071e55ae9c6fbebfe4e5bbbc3af122fc3db0c0c09c4d8955e"}, + {file = "netcdf4-1.7.3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:348e79b4f26f2e403fe3c54364e9297e4ef326c7ee12f9be01c037db853d26c0"}, + {file = "netcdf4-1.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:6ab71f5d70e55e8584d168d5158efdb2fd8d350a033d0c27d942c3d399587f54"}, + {file = "netcdf4-1.7.3-cp311-abi3-macosx_13_0_x86_64.whl", hash = "sha256:801c222d8ad35fd7dc7e9aa7ea6373d184bcb3b8ee6b794c5fbecaa5155b1792"}, + {file = "netcdf4-1.7.3-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:83dbfd6f10a0ec785d5296016bd821bbe9f0df780be72fc00a1f0d179d9c5f0f"}, + {file = "netcdf4-1.7.3-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:949e086d4d2612b49e5b95f60119d216c9ceb7b17bc771e9e0fa0e9b9c0a2f9f"}, + {file = "netcdf4-1.7.3-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c764ba6f6a1421cab5496097e8a1c4d2e36be2a04880dfd288bb61b348c217e"}, + {file = "netcdf4-1.7.3-cp311-abi3-win_amd64.whl", hash = "sha256:1b6c646fa179fb1e5e8d6e8231bc78cc0311eceaa1241256b5a853f1d04055b9"}, + {file = "netcdf4-1.7.3.tar.gz", hash = "sha256:83f122fc3415e92b1d4904fd6a0898468b5404c09432c34beb6b16c533884673"}, +] + +[package.dependencies] +certifi = "*" +cftime = "*" +numpy = "*" + +[package.extras] +parallel = ["mpi4py"] +tests = ["Cython", "packaging", "pytest", "typing-extensions (>=4.15.0)"] + +[[package]] +name = "netcdf4" +version = "1.7.4" +description = "Provides an object-oriented python interface to the netCDF version 4 library" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "platform_system != \"Windows\" or platform_machine != \"ARM64\" or python_version >= \"3.11\"" +files = [ + {file = "netcdf4-1.7.4-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:b1c1a7ea3678db76bf33d14f7e202385d634db38c5e70d8cf4895971023eebb9"}, + {file = "netcdf4-1.7.4-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:d3f9497873454207f9480847d02b1b19a4bc81ad6e9166e1c17d4e2f8f3555d1"}, + {file = "netcdf4-1.7.4-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8e18294af803e80f8c0339f791901942e268c334c099bbd5f7ea8325a49801a"}, + {file = "netcdf4-1.7.4-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0b06c0b93fd0ecc1ec67a582f3ba98b7db9da1fa843c8f83fd75990e3701771e"}, + {file = "netcdf4-1.7.4-cp310-cp310-win_amd64.whl", hash = "sha256:889ba77f084504aebaba9c6f9a88ac213431fef0e897f887cd35aef351ff7740"}, + {file = "netcdf4-1.7.4-cp311-abi3-macosx_13_0_x86_64.whl", hash = "sha256:dec70e809cc65b04ebe95113ee9c85ba46a51c3a37c058d2b2b0cadc4d3052d8"}, + {file = "netcdf4-1.7.4-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:75cf59100f0775bc4d6b9d4aca7cbabd12e2b8cf3b9a4fb16d810b92743a315a"}, + {file = "netcdf4-1.7.4-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddfc7e9d261125c74708119440c85ea288b5fee41db676d2ba1ce9be11f96932"}, + {file = "netcdf4-1.7.4-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a72c9f58767779ec14cb7451c3b56bdd8fdc027a792fac2062b14e090c5617f3"}, + {file = "netcdf4-1.7.4-cp311-abi3-win_amd64.whl", hash = "sha256:9476e1f23161ae5159cd1548c50c8a37922e77d76583e247133f256ef7b825fc"}, + {file = "netcdf4-1.7.4-cp311-abi3-win_arm64.whl", hash = "sha256:876ad9d58f09c98741c066c726164c45a098a58fb90e5fac9e74de4bb8a793fd"}, + {file = "netcdf4-1.7.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56688c03444fffe0d0c7512cb45245e650389cd841c955b30e4552fa681c4cd9"}, + {file = "netcdf4-1.7.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ecf471ba8a6ddb2200121949bedfa0095db228822f38227d5da680694a38358"}, + {file = "netcdf4-1.7.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5841de0735e8e4875b367c668e81d334287858d64dd9f3e3e2261e808c84922"}, + {file = "netcdf4-1.7.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86fac03a8c5b250d57866e7d98918a64742e4b0de1681c5c86bac5726bab8aee"}, + {file = "netcdf4-1.7.4-cp314-cp314t-macosx_13_0_x86_64.whl", hash = "sha256:ad083d260301b5add74b1669c75ab0df03bdf986decfcc092cb45eec2615b5f1"}, + {file = "netcdf4-1.7.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f22014092cc9da3f056b0368e2e38c42afd5725c87ad4843eb2f467e16dd4f6"}, + {file = "netcdf4-1.7.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:224a15434c165a5e0225e5831f591edf62533044b1ce62fdfee815195bbd077d"}, + {file = "netcdf4-1.7.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31a2318305de6831a18df25ad0df9f03b6d68666af0356d4f6057d66c02ffeb6"}, + {file = "netcdf4-1.7.4-cp314-cp314t-win_amd64.whl", hash = "sha256:6c4a0aa9446c3a616ef3be015b629dc6173643f8b09546de26a4e40e272cd1ed"}, + {file = "netcdf4-1.7.4-cp314-cp314t-win_arm64.whl", hash = "sha256:034220887d48da032cb2db5958f69759dbb04eb33e279ec6390571d4aea734fe"}, + {file = "netcdf4-1.7.4.tar.gz", hash = "sha256:cdbfdc92d6f4d7192ca8506c9b3d4c1d9892969ff28d8e8e1fc97ca08bf12164"}, +] + +[package.dependencies] +certifi = "*" +cftime = "*" +numpy = [ + {version = ">=1.21.2", markers = "platform_system != \"Windows\" or platform_machine != \"ARM64\""}, + {version = ">=2.3.0", markers = "platform_system == \"Windows\" and platform_machine == \"ARM64\""}, +] + +[package.extras] +parallel = ["mpi4py"] +tests = ["Cython", "packaging", "pytest", "typing-extensions (>=4.15.0)"] + +[[package]] +name = "networkx" +version = "3.4.2" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version < \"3.11\"" +files = [ + {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, + {file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"}, +] + +[package.extras] +default = ["matplotlib (>=3.7)", "numpy (>=1.24)", "pandas (>=2.0)", "scipy (>=1.10,!=1.11.0,!=1.11.1)"] +developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] +doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.15)", "sphinx (>=7.3)", "sphinx-gallery (>=0.16)", "texext (>=0.6.7)"] +example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=1.9)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] +extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] + +[[package]] +name = "networkx" +version = "3.6" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.11" +groups = ["main"] +markers = "python_version == \"3.14\"" +files = [ + {file = "networkx-3.6-py3-none-any.whl", hash = "sha256:cdb395b105806062473d3be36458d8f1459a4e4b98e236a66c3a48996e07684f"}, + {file = "networkx-3.6.tar.gz", hash = "sha256:285276002ad1f7f7da0f7b42f004bcba70d381e936559166363707fdad3d72ad"}, +] + +[package.extras] +benchmarking = ["asv", "virtualenv"] +default = ["matplotlib (>=3.8)", "numpy (>=1.25)", "pandas (>=2.0)", "scipy (>=1.11.2)"] +developer = ["mypy (>=1.15)", "pre-commit (>=4.1)"] +doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=10)", "pydata-sphinx-theme (>=0.16)", "sphinx (>=8.0)", "sphinx-gallery (>=0.18)", "texext (>=0.6.7)"] +example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "iplotx (>=0.9.0)", "momepy (>=0.7.2)", "osmnx (>=2.0.0)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] +extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] +release = ["build (>=0.10)", "changelist (==0.5)", "twine (>=4.0)", "wheel (>=0.40)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)", "pytest-xdist (>=3.0)"] +test-extras = ["pytest-mpl", "pytest-randomly"] + +[[package]] +name = "networkx" +version = "3.6.1" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = "!=3.14.1,>=3.11" +groups = ["main"] +markers = "python_version >= \"3.11\" and python_version < \"3.14\"" +files = [ + {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, + {file = "networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509"}, +] + +[package.extras] +benchmarking = ["asv", "virtualenv"] +default = ["matplotlib (>=3.8)", "numpy (>=1.25)", "pandas (>=2.0)", "scipy (>=1.11.2)"] +developer = ["mypy (>=1.15)", "pre-commit (>=4.1)"] +doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=10)", "pydata-sphinx-theme (>=0.16)", "sphinx (>=8.0)", "sphinx-gallery (>=0.18)", "texext (>=0.6.7)"] +example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "iplotx (>=0.9.0)", "momepy (>=0.7.2)", "osmnx (>=2.0.0)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] +extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] +release = ["build (>=0.10)", "changelist (==0.5)", "twine (>=4.0)", "wheel (>=0.40)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)", "pytest-xdist (>=3.0)"] +test-extras = ["pytest-mpl", "pytest-randomly"] + [[package]] name = "notebook" -version = "7.5.4" +version = "7.5.6" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "notebook-7.5.4-py3-none-any.whl", hash = "sha256:860e31782b3d3a25ca0819ff039f5cf77845d1bf30c78ef9528b88b25e0a9850"}, - {file = "notebook-7.5.4.tar.gz", hash = "sha256:b928b2ba22cb63aa83df2e0e76fe3697950a0c1c4a41b84ebccf1972b1bb5771"}, + {file = "notebook-7.5.6-py3-none-any.whl", hash = "sha256:4dde3f8fb55fa8fb7946d58c6e869ce9baf46d00fc070664f62604569d0faca0"}, + {file = "notebook-7.5.6.tar.gz", hash = "sha256:621174aade80108f0020b0f00738000b215f75fa3cd90771ad7aa0f24536a4e1"}, ] [package.dependencies] jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.5.5,<4.6" +jupyterlab = ">=4.5.7,<4.6" jupyterlab-server = ">=2.28.0,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" @@ -2349,7 +2821,7 @@ description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" groups = ["main", "examples"] -markers = "python_version == \"3.10\"" +markers = "python_version < \"3.11\"" files = [ {file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}, {file = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"}, @@ -2410,87 +2882,201 @@ files = [ [[package]] name = "numpy" -version = "2.4.2" +version = "2.4.6" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" groups = ["main", "examples"] markers = "python_version >= \"3.11\"" files = [ - {file = "numpy-2.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825"}, - {file = "numpy-2.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1"}, - {file = "numpy-2.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7"}, - {file = "numpy-2.4.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73"}, - {file = "numpy-2.4.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1"}, - {file = "numpy-2.4.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32"}, - {file = "numpy-2.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390"}, - {file = "numpy-2.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413"}, - {file = "numpy-2.4.2-cp311-cp311-win32.whl", hash = "sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda"}, - {file = "numpy-2.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695"}, - {file = "numpy-2.4.2-cp311-cp311-win_arm64.whl", hash = "sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3"}, - {file = "numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a"}, - {file = "numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1"}, - {file = "numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e"}, - {file = "numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27"}, - {file = "numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548"}, - {file = "numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f"}, - {file = "numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460"}, - {file = "numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba"}, - {file = "numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f"}, - {file = "numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85"}, - {file = "numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa"}, - {file = "numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c"}, - {file = "numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979"}, - {file = "numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98"}, - {file = "numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef"}, - {file = "numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7"}, - {file = "numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499"}, - {file = "numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb"}, - {file = "numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7"}, - {file = "numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110"}, - {file = "numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622"}, - {file = "numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71"}, - {file = "numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262"}, - {file = "numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913"}, - {file = "numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab"}, - {file = "numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82"}, - {file = "numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f"}, - {file = "numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554"}, - {file = "numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257"}, - {file = "numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657"}, - {file = "numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b"}, - {file = "numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1"}, - {file = "numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b"}, - {file = "numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000"}, - {file = "numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1"}, - {file = "numpy-2.4.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74"}, - {file = "numpy-2.4.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a"}, - {file = "numpy-2.4.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325"}, - {file = "numpy-2.4.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909"}, - {file = "numpy-2.4.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a"}, - {file = "numpy-2.4.2-cp314-cp314-win32.whl", hash = "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a"}, - {file = "numpy-2.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75"}, - {file = "numpy-2.4.2-cp314-cp314-win_arm64.whl", hash = "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05"}, - {file = "numpy-2.4.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308"}, - {file = "numpy-2.4.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef"}, - {file = "numpy-2.4.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d"}, - {file = "numpy-2.4.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8"}, - {file = "numpy-2.4.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5"}, - {file = "numpy-2.4.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e"}, - {file = "numpy-2.4.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a"}, - {file = "numpy-2.4.2-cp314-cp314t-win32.whl", hash = "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443"}, - {file = "numpy-2.4.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236"}, - {file = "numpy-2.4.2-cp314-cp314t-win_arm64.whl", hash = "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181"}, - {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082"}, - {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a"}, - {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920"}, - {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821"}, - {file = "numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb"}, - {file = "numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0"}, - {file = "numpy-2.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0"}, - {file = "numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae"}, + {file = "numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4"}, + {file = "numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d"}, + {file = "numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8"}, + {file = "numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538"}, + {file = "numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47"}, + {file = "numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93"}, + {file = "numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8"}, + {file = "numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6"}, + {file = "numpy-2.4.6-cp311-cp311-win32.whl", hash = "sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8"}, + {file = "numpy-2.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147"}, + {file = "numpy-2.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698"}, + {file = "numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f"}, + {file = "numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853"}, + {file = "numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a"}, + {file = "numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2"}, + {file = "numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45"}, + {file = "numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751"}, + {file = "numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3"}, + {file = "numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b"}, + {file = "numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089"}, + {file = "numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a"}, + {file = "numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605"}, + {file = "numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91"}, + {file = "numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359"}, + {file = "numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778"}, + {file = "numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1"}, + {file = "numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe"}, + {file = "numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997"}, + {file = "numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20"}, + {file = "numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d"}, + {file = "numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67"}, + {file = "numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd"}, + {file = "numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab"}, + {file = "numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75"}, + {file = "numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096"}, + {file = "numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b"}, + {file = "numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8"}, + {file = "numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402"}, + {file = "numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb"}, + {file = "numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1"}, + {file = "numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261"}, + {file = "numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6"}, + {file = "numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a"}, + {file = "numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e"}, + {file = "numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e"}, + {file = "numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43"}, + {file = "numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e"}, + {file = "numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895"}, + {file = "numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4"}, + {file = "numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063"}, + {file = "numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627"}, + {file = "numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73"}, + {file = "numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda"}, +] + +[[package]] +name = "openfast-io" +version = "5.0.0" +description = "Readers and writers for OpenFAST files." +optional = false +python-versions = ">3.10" +groups = ["main"] +files = [ + {file = "openfast_io-5.0.0-py3-none-any.whl", hash = "sha256:3558880af3af7d319e1644c3063eb44f067bd50db727b68dfc4578250deda093"}, + {file = "openfast_io-5.0.0.tar.gz", hash = "sha256:5b683f2f381eee506d1a6ce90e3324273c027dea831b9dd969edc6254ce61241"}, +] + +[package.dependencies] +deepdiff = ">8.0" +numpy = ">1.0" +pandas = ">2.0" +ruamel-yaml = ">0.18" + +[package.extras] +all = ["rosco (>2.9.2)", "xlrd (>2.0)"] +rosco = ["rosco (>2.9.2)"] +xlrd = ["xlrd (>2.0)"] + +[[package]] +name = "openmdao" +version = "3.43.0" +description = "OpenMDAO framework infrastructure" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "openmdao-3.43.0-py3-none-any.whl", hash = "sha256:fc98acea841df58710ffd2bfe1f34692901272ddd10b603522e7f37955259093"}, + {file = "openmdao-3.43.0.tar.gz", hash = "sha256:be5990817751f3897eb561e6c331feff9998fbea637db4718e54dfa01e477b1b"}, +] + +[package.dependencies] +networkx = ">=3.3" +numpy = ">=2.0,<2.4.0 || >2.4.0" +packaging = "*" +requests = "*" +scipy = ">=1.13" + +[package.extras] +all = ["aiounittest", "bokeh (>=3.4.0)", "colorama", "coverage (>=7.6.0)", "idna (>=3.7)", "ipympl", "ipyparallel", "jax (>=0.4.0)", "jaxlib (>=0.4.0)", "jinja2 (>=3.1.4)", "jupyter-book (>=1.0.3,<2)", "matplotlib", "notebook", "num2words", "numpydoc (>=1.1)", "panel", "parameterized", "playwright (>=1.20)", "pre-commit", "pycodestyle (>=2.4.0)", "pydocstyle (>=2.0.0)", "pydoe3", "rich", "sphinx-sitemap", "testflo (>=1.3.6)", "tqdm (>=4.66.3)", "websockets (>8)"] +docs = ["idna (>=3.7)", "ipyparallel", "jinja2 (>=3.1.4)", "jupyter-book (>=1.0.3,<2)", "matplotlib", "numpydoc (>=1.1)", "sphinx-sitemap", "tqdm (>=4.66.3)"] +doe = ["pydoe3"] +jax = ["jax (>=0.4.0)", "jaxlib (>=0.4.0)"] +julia = ["omjlcomps (>=0.2.6)"] +notebooks = ["idna (>=3.7)", "ipympl", "notebook"] +numba = ["numba"] +test = ["aiounittest", "coverage (>=7.6.0)", "num2words", "numpydoc (>=1.1)", "parameterized", "playwright (>=1.20)", "pre-commit", "pycodestyle (>=2.4.0)", "pydocstyle (>=2.0.0)", "testflo (>=1.3.6)", "websockets (>8)"] +visualization = ["bokeh (>=3.4.0)", "colorama", "matplotlib", "panel", "rich"] + +[[package]] +name = "openpyxl" +version = "3.1.5" +description = "A Python library to read/write Excel 2010 xlsx/xlsm files" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, + {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, +] + +[package.dependencies] +et-xmlfile = "*" + +[[package]] +name = "orbit-nrel" +version = "1.3" +description = "Offshore Renewables Balance of system and Installation Tool" +optional = false +python-versions = ">3.9" +groups = ["main"] +files = [ + {file = "orbit_nrel-1.3-py3-none-any.whl", hash = "sha256:011925d18deb982f8265f35c4af30047807f5a08dc0b0fcb5f594b4eab15c8a2"}, + {file = "orbit_nrel-1.3.tar.gz", hash = "sha256:3cf16a4f4dec822c85b04743ca1ab6eebb830e47d2205b7cdcf95cb7ccc05537"}, +] + +[package.dependencies] +marmot-agents = ">=0.2.5" +matplotlib = "*" +numpy = "*" +pandas = "*" +python-benedict = "*" +pyyaml = "*" +scipy = "*" +simpy = "*" +statsmodels = "*" + +[package.extras] +dev = ["black", "isort", "pre-commit", "pytest (>=9)", "pytest-cov", "ruff"] +docs = ["jupyter-book (>=1,<2)", "linkify-it-py (>=2)", "myst-nb (>=0.16)", "myst-parser (>=0.17)", "nbformat (>=5.0.0)", "sphinx-autodoc-typehints", "sphinxcontrib-autoyaml", "sphinxcontrib-bibtex (>=2.4)", "sphinxcontrib-spelling (>=7)"] + +[[package]] +name = "orderly-set" +version = "5.5.0" +description = "Orderly set" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "orderly_set-5.5.0-py3-none-any.whl", hash = "sha256:46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7"}, + {file = "orderly_set-5.5.0.tar.gz", hash = "sha256:e87185c8e4d8afa64e7f8160ee2c542a475b738bc891dc3f58102e654125e6ce"}, ] +[package.extras] +coverage = ["coverage (>=7.6.0,<7.7.0)"] +dev = ["bump2version (>=1.0.0,<1.1.0)", "ipdb (>=0.13.0,<0.14.0)"] +optimize = ["orjson"] +static = ["flake8 (>=7.1.0,<7.2.0)", "flake8-pyproject (>=1.2.3,<1.3.0)"] +test = ["pytest (>=8.3.0,<8.4.0)", "pytest-benchmark (>=5.1.0,<5.2.0)", "pytest-cov (>=6.0.0,<6.1.0)", "python-dotenv (>=1.0.0,<1.1.0)"] + [[package]] name = "overrides" version = "7.7.0" @@ -2498,7 +3084,7 @@ description = "A decorator to automatically detect mismatch when overriding a me optional = false python-versions = ">=3.6" groups = ["dev"] -markers = "python_version < \"3.12\"" +markers = "python_version <= \"3.11\"" files = [ {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, @@ -2506,14 +3092,14 @@ files = [ [[package]] name = "packaging" -version = "26.0" +version = "26.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" groups = ["main", "dev", "examples"] files = [ - {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, - {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, + {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"}, + {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"}, ] [[package]] @@ -2630,14 +3216,14 @@ files = [ [[package]] name = "parso" -version = "0.8.6" +version = "0.8.7" description = "A Python Parser" optional = false python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "parso-0.8.6-py2.py3-none-any.whl", hash = "sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff"}, - {file = "parso-0.8.6.tar.gz", hash = "sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd"}, + {file = "parso-0.8.7-py2.py3-none-any.whl", hash = "sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c"}, + {file = "parso-0.8.7.tar.gz", hash = "sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1"}, ] [package.extras] @@ -2664,21 +3250,38 @@ ppft = ">=1.7.8" [[package]] name = "pathspec" -version = "1.0.4" +version = "1.1.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723"}, - {file = "pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645"}, + {file = "pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189"}, + {file = "pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a"}, ] [package.extras] hyperscan = ["hyperscan (>=0.7)"] optional = ["typing-extensions (>=4)"] re2 = ["google-re2 (>=1.1)"] -tests = ["pytest (>=9)", "typing-extensions (>=4.15)"] + +[[package]] +name = "patsy" +version = "1.0.2" +description = "A Python package for describing statistical models and for building design matrices." +optional = false +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a"}, + {file = "patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0"}, +] + +[package.dependencies] +numpy = ">=1.4" + +[package.extras] +test = ["pytest", "pytest-cov", "scipy"] [[package]] name = "pexpect" @@ -2698,103 +3301,103 @@ ptyprocess = ">=0.5" [[package]] name = "pillow" -version = "12.1.1" +version = "12.2.0" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" groups = ["main", "examples"] files = [ - {file = "pillow-12.1.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f1625b72740fdda5d77b4def688eb8fd6490975d06b909fd19f13f391e077e0"}, - {file = "pillow-12.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:178aa072084bd88ec759052feca8e56cbb14a60b39322b99a049e58090479713"}, - {file = "pillow-12.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b66e95d05ba806247aaa1561f080abc7975daf715c30780ff92a20e4ec546e1b"}, - {file = "pillow-12.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:89c7e895002bbe49cdc5426150377cbbc04767d7547ed145473f496dfa40408b"}, - {file = "pillow-12.1.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a5cbdcddad0af3da87cb16b60d23648bc3b51967eb07223e9fed77a82b457c4"}, - {file = "pillow-12.1.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9f51079765661884a486727f0729d29054242f74b46186026582b4e4769918e4"}, - {file = "pillow-12.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:99c1506ea77c11531d75e3a412832a13a71c7ebc8192ab9e4b2e355555920e3e"}, - {file = "pillow-12.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36341d06738a9f66c8287cf8b876d24b18db9bd8740fa0672c74e259ad408cff"}, - {file = "pillow-12.1.1-cp310-cp310-win32.whl", hash = "sha256:6c52f062424c523d6c4db85518774cc3d50f5539dd6eed32b8f6229b26f24d40"}, - {file = "pillow-12.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6008de247150668a705a6338156efb92334113421ceecf7438a12c9a12dab23"}, - {file = "pillow-12.1.1-cp310-cp310-win_arm64.whl", hash = "sha256:1a9b0ee305220b392e1124a764ee4265bd063e54a751a6b62eff69992f457fa9"}, - {file = "pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e879bb6cd5c73848ef3b2b48b8af9ff08c5b71ecda8048b7dd22d8a33f60be32"}, - {file = "pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:365b10bb9417dd4498c0e3b128018c4a624dc11c7b97d8cc54effe3b096f4c38"}, - {file = "pillow-12.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4ce8e329c93845720cd2014659ca67eac35f6433fd3050393d85f3ecef0dad5"}, - {file = "pillow-12.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc354a04072b765eccf2204f588a7a532c9511e8b9c7f900e1b64e3e33487090"}, - {file = "pillow-12.1.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e7976bf1910a8116b523b9f9f58bf410f3e8aa330cd9a2bb2953f9266ab49af"}, - {file = "pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:597bd9c8419bc7c6af5604e55847789b69123bbe25d65cc6ad3012b4f3c98d8b"}, - {file = "pillow-12.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c1fc0f2ca5f96a3c8407e41cca26a16e46b21060fe6d5b099d2cb01412222f5"}, - {file = "pillow-12.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:578510d88c6229d735855e1f278aa305270438d36a05031dfaae5067cc8eb04d"}, - {file = "pillow-12.1.1-cp311-cp311-win32.whl", hash = "sha256:7311c0a0dcadb89b36b7025dfd8326ecfa36964e29913074d47382706e516a7c"}, - {file = "pillow-12.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:fbfa2a7c10cc2623f412753cddf391c7f971c52ca40a3f65dc5039b2939e8563"}, - {file = "pillow-12.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:b81b5e3511211631b3f672a595e3221252c90af017e399056d0faabb9538aa80"}, - {file = "pillow-12.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab323b787d6e18b3d91a72fc99b1a2c28651e4358749842b8f8dfacd28ef2052"}, - {file = "pillow-12.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:adebb5bee0f0af4909c30db0d890c773d1a92ffe83da908e2e9e720f8edf3984"}, - {file = "pillow-12.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb66b7cc26f50977108790e2456b7921e773f23db5630261102233eb355a3b79"}, - {file = "pillow-12.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee2810642b2898bb187ced9b349e95d2a7272930796e022efaf12e99dccd293"}, - {file = "pillow-12.1.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0b1cd6232e2b618adcc54d9882e4e662a089d5768cd188f7c245b4c8c44a397"}, - {file = "pillow-12.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7aac39bcf8d4770d089588a2e1dd111cbaa42df5a94be3114222057d68336bd0"}, - {file = "pillow-12.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ab174cd7d29a62dd139c44bf74b698039328f45cb03b4596c43473a46656b2f3"}, - {file = "pillow-12.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:339ffdcb7cbeaa08221cd401d517d4b1fe7a9ed5d400e4a8039719238620ca35"}, - {file = "pillow-12.1.1-cp312-cp312-win32.whl", hash = "sha256:5d1f9575a12bed9e9eedd9a4972834b08c97a352bd17955ccdebfeca5913fa0a"}, - {file = "pillow-12.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:21329ec8c96c6e979cd0dfd29406c40c1d52521a90544463057d2aaa937d66a6"}, - {file = "pillow-12.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:af9a332e572978f0218686636610555ae3defd1633597be015ed50289a03c523"}, - {file = "pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d242e8ac078781f1de88bf823d70c1a9b3c7950a44cdf4b7c012e22ccbcd8e4e"}, - {file = "pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:02f84dfad02693676692746df05b89cf25597560db2857363a208e393429f5e9"}, - {file = "pillow-12.1.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e65498daf4b583091ccbb2556c7000abf0f3349fcd57ef7adc9a84a394ed29f6"}, - {file = "pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c6db3b84c87d48d0088943bf33440e0c42370b99b1c2a7989216f7b42eede60"}, - {file = "pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b7e5304e34942bf62e15184219a7b5ad4ff7f3bb5cca4d984f37df1a0e1aee2"}, - {file = "pillow-12.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5bddd742a44b7e6b1e773ab5db102bd7a94c32555ba656e76d319d19c3850"}, - {file = "pillow-12.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc44ef1f3de4f45b50ccf9136999d71abb99dca7706bc75d222ed350b9fd2289"}, - {file = "pillow-12.1.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a8eb7ed8d4198bccbd07058416eeec51686b498e784eda166395a23eb99138e"}, - {file = "pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47b94983da0c642de92ced1702c5b6c292a84bd3a8e1d1702ff923f183594717"}, - {file = "pillow-12.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:518a48c2aab7ce596d3bf79d0e275661b846e86e4d0e7dec34712c30fe07f02a"}, - {file = "pillow-12.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a550ae29b95c6dc13cf69e2c9dc5747f814c54eeb2e32d683e5e93af56caa029"}, - {file = "pillow-12.1.1-cp313-cp313-win32.whl", hash = "sha256:a003d7422449f6d1e3a34e3dd4110c22148336918ddbfc6a32581cd54b2e0b2b"}, - {file = "pillow-12.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:344cf1e3dab3be4b1fa08e449323d98a2a3f819ad20f4b22e77a0ede31f0faa1"}, - {file = "pillow-12.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c0dd1636633e7e6a0afe7bf6a51a14992b7f8e60de5789018ebbdfae55b040a"}, - {file = "pillow-12.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0330d233c1a0ead844fc097a7d16c0abff4c12e856c0b325f231820fee1f39da"}, - {file = "pillow-12.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dae5f21afb91322f2ff791895ddd8889e5e947ff59f71b46041c8ce6db790bc"}, - {file = "pillow-12.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e0c664be47252947d870ac0d327fea7e63985a08794758aa8af5b6cb6ec0c9c"}, - {file = "pillow-12.1.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:691ab2ac363b8217f7d31b3497108fb1f50faab2f75dfb03284ec2f217e87bf8"}, - {file = "pillow-12.1.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9e8064fb1cc019296958595f6db671fba95209e3ceb0c4734c9baf97de04b20"}, - {file = "pillow-12.1.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:472a8d7ded663e6162dafdf20015c486a7009483ca671cece7a9279b512fcb13"}, - {file = "pillow-12.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:89b54027a766529136a06cfebeecb3a04900397a3590fd252160b888479517bf"}, - {file = "pillow-12.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:86172b0831b82ce4f7877f280055892b31179e1576aa00d0df3bb1bbf8c3e524"}, - {file = "pillow-12.1.1-cp313-cp313t-win32.whl", hash = "sha256:44ce27545b6efcf0fdbdceb31c9a5bdea9333e664cda58a7e674bb74608b3986"}, - {file = "pillow-12.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a285e3eb7a5a45a2ff504e31f4a8d1b12ef62e84e5411c6804a42197c1cf586c"}, - {file = "pillow-12.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cc7d296b5ea4d29e6570dabeaed58d31c3fea35a633a69679fb03d7664f43fb3"}, - {file = "pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:417423db963cb4be8bac3fc1204fe61610f6abeed1580a7a2cbb2fbda20f12af"}, - {file = "pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:b957b71c6b2387610f556a7eb0828afbe40b4a98036fc0d2acfa5a44a0c2036f"}, - {file = "pillow-12.1.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:097690ba1f2efdeb165a20469d59d8bb03c55fb6621eb2041a060ae8ea3e9642"}, - {file = "pillow-12.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2815a87ab27848db0321fb78c7f0b2c8649dee134b7f2b80c6a45c6831d75ccd"}, - {file = "pillow-12.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7ed2c6543bad5a7d5530eb9e78c53132f93dfa44a28492db88b41cdab885202"}, - {file = "pillow-12.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:652a2c9ccfb556235b2b501a3a7cf3742148cd22e04b5625c5fe057ea3e3191f"}, - {file = "pillow-12.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6e4571eedf43af33d0fc233a382a76e849badbccdf1ac438841308652a08e1f"}, - {file = "pillow-12.1.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b574c51cf7d5d62e9be37ba446224b59a2da26dc4c1bb2ecbe936a4fb1a7cb7f"}, - {file = "pillow-12.1.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a37691702ed687799de29a518d63d4682d9016932db66d4e90c345831b02fb4e"}, - {file = "pillow-12.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f95c00d5d6700b2b890479664a06e754974848afaae5e21beb4d83c106923fd0"}, - {file = "pillow-12.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:559b38da23606e68681337ad74622c4dbba02254fc9cb4488a305dd5975c7eeb"}, - {file = "pillow-12.1.1-cp314-cp314-win32.whl", hash = "sha256:03edcc34d688572014ff223c125a3f77fb08091e4607e7745002fc214070b35f"}, - {file = "pillow-12.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:50480dcd74fa63b8e78235957d302d98d98d82ccbfac4c7e12108ba9ecbdba15"}, - {file = "pillow-12.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:5cb1785d97b0c3d1d1a16bc1d710c4a0049daefc4935f3a8f31f827f4d3d2e7f"}, - {file = "pillow-12.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1f90cff8aa76835cba5769f0b3121a22bd4eb9e6884cfe338216e557a9a548b8"}, - {file = "pillow-12.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f1be78ce9466a7ee64bfda57bdba0f7cc499d9794d518b854816c41bf0aa4e9"}, - {file = "pillow-12.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:42fc1f4677106188ad9a55562bbade416f8b55456f522430fadab3cef7cd4e60"}, - {file = "pillow-12.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98edb152429ab62a1818039744d8fbb3ccab98a7c29fc3d5fcef158f3f1f68b7"}, - {file = "pillow-12.1.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d470ab1178551dd17fdba0fef463359c41aaa613cdcd7ff8373f54be629f9f8f"}, - {file = "pillow-12.1.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6408a7b064595afcab0a49393a413732a35788f2a5092fdc6266952ed67de586"}, - {file = "pillow-12.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5d8c41325b382c07799a3682c1c258469ea2ff97103c53717b7893862d0c98ce"}, - {file = "pillow-12.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7697918b5be27424e9ce568193efd13d925c4481dd364e43f5dff72d33e10f8"}, - {file = "pillow-12.1.1-cp314-cp314t-win32.whl", hash = "sha256:d2912fd8114fc5545aa3a4b5576512f64c55a03f3ebcca4c10194d593d43ea36"}, - {file = "pillow-12.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4ceb838d4bd9dab43e06c363cab2eebf63846d6a4aeaea283bbdfd8f1a8ed58b"}, - {file = "pillow-12.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7b03048319bfc6170e93bd60728a1af51d3dd7704935feb228c4d4faab35d334"}, - {file = "pillow-12.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:600fd103672b925fe62ed08e0d874ea34d692474df6f4bf7ebe148b30f89f39f"}, - {file = "pillow-12.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:665e1b916b043cef294bc54d47bf02d87e13f769bc4bc5fa225a24b3a6c5aca9"}, - {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:495c302af3aad1ca67420ddd5c7bd480c8867ad173528767d906428057a11f0e"}, - {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fd420ef0c52c88b5a035a0886f367748c72147b2b8f384c9d12656678dfdfa9"}, - {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f975aa7ef9684ce7e2c18a3aa8f8e2106ce1e46b94ab713d156b2898811651d3"}, - {file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8089c852a56c2966cf18835db62d9b34fef7ba74c726ad943928d494fa7f4735"}, - {file = "pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e"}, - {file = "pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4"}, + {file = "pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f"}, + {file = "pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97"}, + {file = "pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff"}, + {file = "pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec"}, + {file = "pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136"}, + {file = "pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c"}, + {file = "pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3"}, + {file = "pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa"}, + {file = "pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032"}, + {file = "pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5"}, + {file = "pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024"}, + {file = "pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab"}, + {file = "pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65"}, + {file = "pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7"}, + {file = "pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e"}, + {file = "pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705"}, + {file = "pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176"}, + {file = "pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b"}, + {file = "pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909"}, + {file = "pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808"}, + {file = "pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60"}, + {file = "pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe"}, + {file = "pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5"}, + {file = "pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421"}, + {file = "pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987"}, + {file = "pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76"}, + {file = "pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005"}, + {file = "pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780"}, + {file = "pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5"}, + {file = "pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5"}, + {file = "pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940"}, + {file = "pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5"}, + {file = "pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414"}, + {file = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c"}, + {file = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2"}, + {file = "pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c"}, + {file = "pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795"}, + {file = "pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f"}, + {file = "pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed"}, + {file = "pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9"}, + {file = "pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed"}, + {file = "pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3"}, + {file = "pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9"}, + {file = "pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795"}, + {file = "pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e"}, + {file = "pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b"}, + {file = "pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06"}, + {file = "pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b"}, + {file = "pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f"}, + {file = "pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612"}, + {file = "pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c"}, + {file = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea"}, + {file = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4"}, + {file = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4"}, + {file = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea"}, + {file = "pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24"}, + {file = "pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98"}, + {file = "pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453"}, + {file = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8"}, + {file = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b"}, + {file = "pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295"}, + {file = "pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed"}, + {file = "pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae"}, + {file = "pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601"}, + {file = "pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be"}, + {file = "pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f"}, + {file = "pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286"}, + {file = "pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50"}, + {file = "pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104"}, + {file = "pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7"}, + {file = "pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150"}, + {file = "pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1"}, + {file = "pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463"}, + {file = "pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3"}, + {file = "pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166"}, + {file = "pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe"}, + {file = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd"}, + {file = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e"}, + {file = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06"}, + {file = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43"}, + {file = "pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354"}, + {file = "pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1"}, + {file = "pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb"}, + {file = "pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f"}, + {file = "pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d"}, + {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f"}, + {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e"}, + {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0"}, + {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1"}, + {file = "pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e"}, + {file = "pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5"}, ] [package.extras] @@ -2807,14 +3410,14 @@ xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.9.2" +version = "4.9.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd"}, - {file = "platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291"}, + {file = "platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917"}, + {file = "platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a"}, ] [[package]] @@ -2899,14 +3502,14 @@ dill = ["dill (>=0.4.1)"] [[package]] name = "prometheus-client" -version = "0.24.1" +version = "0.25.0" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055"}, - {file = "prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9"}, + {file = "prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1"}, + {file = "prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28"}, ] [package.extras] @@ -2998,23 +3601,42 @@ version = "3.0" description = "C parser in Python" optional = false python-versions = ">=3.10" -groups = ["dev"] -markers = "implementation_name != \"PyPy\"" +groups = ["main", "dev"] files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] +markers = {main = "implementation_name == \"pypy\"", dev = "implementation_name != \"PyPy\""} + +[[package]] +name = "pydoe3" +version = "1.6.2" +description = "Design of experiments for Python" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "pydoe3-1.6.2-py2.py3-none-any.whl", hash = "sha256:21b5c3ef10a350bed01f59df54ae262fd1eda9983efac294b679988f311f3445"}, + {file = "pydoe3-1.6.2.tar.gz", hash = "sha256:ff7377c30e0a2ea8af3f074723488779f557457c8b74029965896c30b8a1a541"}, +] + +[package.dependencies] +numpy = "*" +scipy = "*" + +[package.extras] +docs = ["mkdocs (>=1.6.1)", "mkdocs-material (>=9.6.22)", "mkdocs-minify-plugin (>=0.8.0)", "mkdocstrings[python] (>=0.30.1)", "pymdown-extensions (>=10.16.1)"] [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, - {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, ] [package.extras] @@ -3037,15 +3659,15 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pyreadline3" -version = "3.5.4" +version = "3.5.6" description = "A python implementation of GNU readline." optional = false python-versions = ">=3.8" groups = ["main"] markers = "sys_platform == \"win32\"" files = [ - {file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"}, - {file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"}, + {file = "pyreadline3-3.5.6-py3-none-any.whl", hash = "sha256:8449b734232e42a5dcd74048e39b60db2839a4c38cf3ae2bf7707d58b5389c0d"}, + {file = "pyreadline3-3.5.6.tar.gz", hash = "sha256:61e53218b99656091ddb077df9e71f25850e72e030b6183b39c9b7e6e4f4a9bf"}, ] [package.extras] @@ -3074,6 +3696,34 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +[[package]] +name = "python-benedict" +version = "0.37.0" +description = "python-benedict is a dict subclass with keylist/keypath/keyattr support, normalized I/O operations (base64, csv, ini, json, pickle, plist, query-string, toml, xls, xml, yaml) and many utilities... for humans, obviously." +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "python_benedict-0.37.0-py3-none-any.whl", hash = "sha256:532ac2d94cfbfef7269984132e42a0b55330ab4275267958ce07301251da46cc"}, + {file = "python_benedict-0.37.0.tar.gz", hash = "sha256:d2c7d711f45fbb8fdc128c0463b6ad654d68f0c9caeeedd13ed37e5048fc04f3"}, +] + +[package.dependencies] +python-slugify = ">=7.0.0,<9.0.0" +typing_extensions = ">=4.13.2,<4.16.0" + +[package.extras] +all = ["python-benedict[io,parse,s3,schema]"] +html = ["beautifulsoup4 (>=4.12.0,<5.0.0)", "python-benedict[xml]"] +io = ["python-benedict[html,toml,xls,xml,yaml]", "python-fsutil (>=0.16.1,<1.0.0)", "requests (>=2.33.0,<3.0.0)"] +parse = ["ftfy (>=6.0.0,<7.0.0)", "mailchecker (>=4.1.0,<7.0.0)", "phonenumbers (>=8.12.0,<10.0.0)", "python-dateutil (>=2.8.0,<3.0.0)"] +s3 = ["boto3 (>=1.24.89,<2.0.0)", "python-fsutil (>=0.16.1,<1.0.0)"] +schema = ["pydantic (>=2.0.0,<3.0.0)"] +toml = ["tomli (>=2.0.0,<3.0.0) ; python_version < \"3.11\"", "tomli-w (>=1.0.0,<2.0.0)"] +xls = ["openpyxl (>=3.0.0,<4.0.0)", "python-fsutil (>=0.16.1,<1.0.0)", "xlrd (>=2.0.0,<3.0.0)"] +xml = ["xmltodict (>=0.12.0,<2.0.0)"] +yaml = ["pyyaml (>=6.0,<7.0)"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -3091,29 +3741,47 @@ six = ">=1.5" [[package]] name = "python-json-logger" -version = "4.0.0" +version = "4.1.0" description = "JSON Log Formatter for the Python Logging Package" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2"}, - {file = "python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f"}, + {file = "python_json_logger-4.1.0-py3-none-any.whl", hash = "sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2"}, + {file = "python_json_logger-4.1.0.tar.gz", hash = "sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195"}, ] [package.extras] -dev = ["backports.zoneinfo ; python_version < \"3.9\"", "black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec ; implementation_name != \"pypy\"", "mypy", "orjson ; implementation_name != \"pypy\"", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] +dev = ["black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec ; implementation_name != \"pypy\"", "mypy", "orjson ; implementation_name != \"pypy\"", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] + +[[package]] +name = "python-slugify" +version = "8.0.4" +description = "A Python slugify application that also handles Unicode" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, + {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, +] + +[package.dependencies] +text-unidecode = ">=1.3" + +[package.extras] +unidecode = ["Unidecode (>=1.1.1)"] [[package]] name = "pytz" -version = "2025.2" +version = "2026.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" groups = ["main"] files = [ - {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, - {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, + {file = "pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126"}, + {file = "pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a"}, ] [[package]] @@ -3232,7 +3900,7 @@ version = "27.1.0" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.8" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4"}, {file = "pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556"}, @@ -3337,7 +4005,7 @@ version = "0.37.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.10" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -3350,25 +4018,25 @@ typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "requests" -version = "2.32.5" +version = "2.34.2" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.9" -groups = ["dev"] +python-versions = ">=3.10" +groups = ["main", "dev"] files = [ - {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, - {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, + {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, + {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, ] [package.dependencies] -certifi = ">=2017.4.17" +certifi = ">=2023.5.7" charset_normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +urllib3 = ">=1.26,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] name = "rfc3339-validator" @@ -3415,13 +4083,81 @@ lark = ">=1.2.2" [package.extras] testing = ["pytest (>=8.3.5)"] +[[package]] +name = "rosco" +version = "2.10.4" +description = "A reference open source controller toolset for wind turbine applications." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "rosco-2.10.4-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:58b8744a6a8c66a16fb48c27b2846320cfc26b03bb5533581184543459ce804f"}, + {file = "rosco-2.10.4-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:b6e932f0c6e2055950dfa81b1d5c10a5ce4278f5bd71f5cf52a3363c1938f574"}, + {file = "rosco-2.10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a40d9aee6618d95b0a8f9bccbfcd3c30d62daa847f699a14b1f8c4848b19b136"}, + {file = "rosco-2.10.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e98960b71fc0e1b72a56b47974b8f11cc850df976e305e7705567e37a6843bb"}, + {file = "rosco-2.10.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bb08688239e6a8fe97e82cb86003cc30825600e0fbbd06c5244d980bd1b67ed"}, + {file = "rosco-2.10.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:bb43839d10b87d45320d930b2a7632f8257d3df74070cce336c0a21f1216e6d0"}, + {file = "rosco-2.10.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:798759543f92dfbf0ab3be304f7d5a758c709702eb8529cc229699a496a2bb22"}, + {file = "rosco-2.10.4-cp310-cp310-win_amd64.whl", hash = "sha256:9d7d9b3c376b3dd7a5065b323e53382168908797acdf5c56341f9b9784513613"}, + {file = "rosco-2.10.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bbc0eb6d2d743ee001329a3dffb05c2a9f16c7a12117d21f1240b5b55826f7d1"}, + {file = "rosco-2.10.4-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:1d623e9747bd416798edcb915f9c7aabc11e2ba606479f41dc630f05979d9fe8"}, + {file = "rosco-2.10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b91f51ba2a7cb91e3e14e7f21099df075c5667dccd877c789386c63ad45fc0c"}, + {file = "rosco-2.10.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:764b5d07c63c30b22eff9b9b361b3468cde114568767f725febfffe96f8f9091"}, + {file = "rosco-2.10.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f4301427aabfd2764c65786cd058e975a986ccc52883ff0bdabcc58f182113"}, + {file = "rosco-2.10.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e45628f6e95ccb2e2a83fa4039a95fc0e3254cb8c7a6873076fa0e26d013381"}, + {file = "rosco-2.10.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f19795c0b8fb08d60aa9bf8077faee59d07228e32554eb70af5eaef3ab82c803"}, + {file = "rosco-2.10.4-cp311-cp311-win_amd64.whl", hash = "sha256:cdd8e01aff72f553dd4f112deeed33984b681e44598d33c3f5d70a6441f68b03"}, + {file = "rosco-2.10.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3cef4ebad5fa6c1c110154a8cc212c721c8c162ff0875196500979dbfa9e0b54"}, + {file = "rosco-2.10.4-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:3a79547b516c899a2db1bc446a64d7b01d25a1d4cc6f058e073e7b126489a803"}, + {file = "rosco-2.10.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7103499a61bbc2a8510423ac5a43840372983dd7d1bf99cbe99fcde1cec621e4"}, + {file = "rosco-2.10.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d795a2f1615a3ff281a36f62132ed24e1791726ad7c8a66bf4c4897315c6e4e8"}, + {file = "rosco-2.10.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef54a8570861b0a5e5ff030d5b50ea19ba1fcd4e614c8b14124b54b2fa4e988d"}, + {file = "rosco-2.10.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:776a234aab93a0f510eb4b62f5d3448b4d682e20029305c370f1c41678fde539"}, + {file = "rosco-2.10.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03e7ce8282e821fd23d2cf0f933f2a207f2a9611d29e0477890b398d354dc8c4"}, + {file = "rosco-2.10.4-cp312-cp312-win_amd64.whl", hash = "sha256:c85a25eb99aa230670020aad3a9cd17fdb0fc05a35ee5828cdee71060cd89e32"}, + {file = "rosco-2.10.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8d3bf944755ad7c0516238a9b009b5f7990106e6a6aa55ed2d98f3ed514af116"}, + {file = "rosco-2.10.4-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:3b70954bd965278c3e3cc88bb5cfc1a49782fed0ec3214bd81cda0206d52a555"}, + {file = "rosco-2.10.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9651f32435789135b7d1a0f29b335bb82e07cd87e6aaa63d5c39e49752f48ad3"}, + {file = "rosco-2.10.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f34bac456efab5be143f2574f832d507c8583129d7311d8ac87b8c34c4cd3764"}, + {file = "rosco-2.10.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d152646cb400db753efecc786a24b6b028b1d83b4bed0c45d5fe6b0235f3a1d"}, + {file = "rosco-2.10.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b1c2791e865b23c703fbb9bf0a169e2814aedc785f0fa533079fdd09bcaa63fd"}, + {file = "rosco-2.10.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4220572d09b31b27603d3a7ef3fff263dccbdfbfbf4268713600d5db8997adf9"}, + {file = "rosco-2.10.4-cp313-cp313-win_amd64.whl", hash = "sha256:41661ac2089bb6cfaec2399bb9c45dbae4e0f8b3050bbc9c618839cef1f84e80"}, + {file = "rosco-2.10.4-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:74f509eb0415ca5729f508ae783f178568367f5e45950bf3c69513d3f2248f75"}, + {file = "rosco-2.10.4-cp39-cp39-macosx_15_0_arm64.whl", hash = "sha256:0d2002d3a392a285959adcf93990c209632b589099cd6387f4eebf41e549d26b"}, + {file = "rosco-2.10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3aa0b894715242fb9191f2f10e80fed8a53ae9ad361b2346e2028ab73b79831"}, + {file = "rosco-2.10.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:133486ba634d0e47d5d756794b91a62778e2ad94d31aad44e6d33235f40c9765"}, + {file = "rosco-2.10.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d40b16110cc8ee5aed206dc839eee92f62377ecb7b661d5eab560128ecfee653"}, + {file = "rosco-2.10.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:be7f9c7500c2a57899ced8431a1f76b06a32c4f030035914bfb30c3e40961a52"}, + {file = "rosco-2.10.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:632d3dd73a8a7444bc1aad841beda7f5e99839b7009d8d2bdffd64045c6c6c49"}, + {file = "rosco-2.10.4-cp39-cp39-win_amd64.whl", hash = "sha256:9275097a862b263feceed0543dea3d8f81ee89512314c108328c8bdb46e677ad"}, + {file = "rosco-2.10.4.tar.gz", hash = "sha256:15e06f46bd8096dfa6f8cab7b312dacdfe3a88ad3f20fef9f320621cae462aaf"}, +] + +[package.dependencies] +control = "*" +matplotlib = "*" +numpy = "*" +openfast_io = "*" +pandas = "*" +pyparsing = "*" +pyYAML = "*" +pyzmq = "*" +"ruamel.yaml" = "*" +scipy = "*" +wisdem = "*" + +[package.extras] +dev = ["cmake"] +test = ["pytest", "treon"] + [[package]] name = "rpds-py" version = "0.30.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, @@ -3540,6 +4276,24 @@ files = [ {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, ] +[[package]] +name = "ruamel-yaml" +version = "0.19.1" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93"}, + {file = "ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993"}, +] + +[package.extras] +docs = ["mercurial (>5.7)", "ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] +libyaml = ["ruamel.yaml.clibz (>=0.3.7) ; platform_python_implementation == \"CPython\""] +oldlibyaml = ["ruamel.yaml.clib ; platform_python_implementation == \"CPython\""] + [[package]] name = "ruff" version = "0.1.15" @@ -3574,7 +4328,7 @@ description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.10" groups = ["main"] -markers = "python_version == \"3.10\"" +markers = "python_version < \"3.11\"" files = [ {file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"}, {file = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"}, @@ -3730,19 +4484,19 @@ test = ["pytest (>=8)"] [[package]] name = "setuptools" -version = "82.0.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" +version = "82.0.1" +description = "Most extensible Python build backend with support for C/C++ extension modules" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0"}, - {file = "setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb"}, + {file = "setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb"}, + {file = "setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9"}, ] [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.13.0) ; sys_platform != \"cygwin\""] -core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] @@ -3823,6 +4577,18 @@ numpy = ">=1.21" docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] test = ["pytest", "pytest-cov", "scipy-doctest"] +[[package]] +name = "simpy" +version = "4.1.1" +description = "Event discrete, process based simulation for Python." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "simpy-4.1.1-py3-none-any.whl", hash = "sha256:7c5ae380240fd2238671160e4830956f8055830a8317edf5c05e495b3823cd88"}, + {file = "simpy-4.1.1.tar.gz", hash = "sha256:06d0750a7884b11e0e8e20ce0bc7c6d4ed5f1743d456695340d13fdff95001a6"}, +] + [[package]] name = "six" version = "1.17.0" @@ -3835,6 +4601,18 @@ files = [ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "soupsieve" version = "2.8.3" @@ -3867,6 +4645,64 @@ pure-eval = "*" [package.extras] tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] +[[package]] +name = "statsmodels" +version = "0.14.6" +description = "Statistical computations and models for Python" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "statsmodels-0.14.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4ff0649a2df674c7ffb6fa1a06bffdb82a6adf09a48e90e000a15a6aaa734b0"}, + {file = "statsmodels-0.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:109012088b3e370080846ab053c76d125268631410142daad2f8c10770e8e8d9"}, + {file = "statsmodels-0.14.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e93bd5d220f3cb6fc5fc1bffd5b094966cab8ee99f6c57c02e95710513d6ac3f"}, + {file = "statsmodels-0.14.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:06eec42d682fdb09fe5d70a05930857efb141754ec5a5056a03304c1b5e32fd9"}, + {file = "statsmodels-0.14.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0444e88557df735eda7db330806fe09d51c9f888bb1f5906cb3a61fb1a3ed4a8"}, + {file = "statsmodels-0.14.6-cp310-cp310-win_amd64.whl", hash = "sha256:e83a9abe653835da3b37fb6ae04b45480c1de11b3134bd40b09717192a1456ea"}, + {file = "statsmodels-0.14.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ad5c2810fc6c684254a7792bf1cbaf1606cdee2a253f8bd259c43135d87cfb4"}, + {file = "statsmodels-0.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:341fa68a7403e10a95c7b6e41134b0da3a7b835ecff1eb266294408535a06eb6"}, + {file = "statsmodels-0.14.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdf1dfe2a3ca56f5529118baf33a13efed2783c528f4a36409b46bbd2d9d48eb"}, + {file = "statsmodels-0.14.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3764ba8195c9baf0925a96da0743ff218067a269f01d155ca3558deed2658ca"}, + {file = "statsmodels-0.14.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e8d2e519852adb1b420e018f5ac6e6684b2b877478adf7fda2cfdb58f5acb5d"}, + {file = "statsmodels-0.14.6-cp311-cp311-win_amd64.whl", hash = "sha256:2738a00fca51196f5a7d44b06970ace6b8b30289839e4808d656f8a98e35faa7"}, + {file = "statsmodels-0.14.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe76140ae7adc5ff0e60a3f0d56f4fffef484efa803c3efebf2fcd734d72ecb5"}, + {file = "statsmodels-0.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26d4f0ed3b31f3c86f83a92f5c1f5cbe63fc992cd8915daf28ca49be14463a1c"}, + {file = "statsmodels-0.14.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8c00a42863e4f4733ac9d078bbfad816249c01451740e6f5053ecc7db6d6368"}, + {file = "statsmodels-0.14.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19b58cf7474aa9e7e3b0771a66537148b2df9b5884fbf156096c0e6c1ff0469d"}, + {file = "statsmodels-0.14.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:81e7dcc5e9587f2567e52deaff5220b175bf2f648951549eae5fc9383b62bc37"}, + {file = "statsmodels-0.14.6-cp312-cp312-win_amd64.whl", hash = "sha256:b5eb07acd115aa6208b4058211138393a7e6c2cf12b6f213ede10f658f6a714f"}, + {file = "statsmodels-0.14.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:47ee7af083623d2091954fa71c7549b8443168f41b7c5dce66510274c50fd73e"}, + {file = "statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa60d82e29fcd0a736e86feb63a11d2380322d77a9369a54be8b0965a3985f71"}, + {file = "statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89ee7d595f5939cc20bf946faedcb5137d975f03ae080f300ebb4398f16a5bd4"}, + {file = "statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:730f3297b26749b216a06e4327fe0be59b8d05f7d594fb6caff4287b69654589"}, + {file = "statsmodels-0.14.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f1c08befa85e93acc992b72a390ddb7bd876190f1360e61d10cf43833463bc9c"}, + {file = "statsmodels-0.14.6-cp313-cp313-win_amd64.whl", hash = "sha256:8021271a79f35b842c02a1794465a651a9d06ec2080f76ebc3b7adce77d08233"}, + {file = "statsmodels-0.14.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:00781869991f8f02ad3610da6627fd26ebe262210287beb59761982a8fa88cae"}, + {file = "statsmodels-0.14.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:73f305fbf31607b35ce919fae636ab8b80d175328ed38fdc6f354e813b86ee37"}, + {file = "statsmodels-0.14.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e443e7077a6e2d3faeea72f5a92c9f12c63722686eb80bb40a0f04e4a7e267ad"}, + {file = "statsmodels-0.14.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3414e40c073d725007a6603a18247ab7af3467e1af4a5e5a24e4c27bc26673b4"}, + {file = "statsmodels-0.14.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a518d3f9889ef920116f9fa56d0338069e110f823926356946dae83bc9e33e19"}, + {file = "statsmodels-0.14.6-cp314-cp314-win_amd64.whl", hash = "sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721"}, + {file = "statsmodels-0.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4d0c1b0f9f6915619e2a0d3853e5763d4d66876892ad352e7d7b93a737556978"}, + {file = "statsmodels-0.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e0fc891d6358bf376cc0ae1fee10a650478172ae9ba359daba1785fc496cd1a"}, + {file = "statsmodels-0.14.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f52ef0f0b63b8fd11e1ef1c2a1e73a410720b8715c9a83a26d733b6815597fe"}, + {file = "statsmodels-0.14.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b328eafa86a2a67303fdb1d25677d15b70cd2a5229aabec7670ec5ea840f1375"}, + {file = "statsmodels-0.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:3bef39f8587754f2d644b2e831e102fa08ace9a5a1af4b583b122e6fd3e083ab"}, + {file = "statsmodels-0.14.6.tar.gz", hash = "sha256:4d17873d3e607d398b85126cd4ed7aad89e4e9d89fc744cdab1af3189a996c2a"}, +] + +[package.dependencies] +numpy = ">=1.22.3,<3" +packaging = ">=21.3" +pandas = ">=1.4,<2.1.0 || >2.1.0" +patsy = ">=0.5.6" +scipy = ">=1.8,<1.9.2 || >1.9.2" + +[package.extras] +build = ["cython (>=3.0.10)"] +develop = ["colorama", "cython (>=3.0.10)", "cython (>=3.0.10,<4)", "flake8", "isort", "jinja2", "joblib", "matplotlib (>=3)", "pytest (>=7.3.0,<8)", "pytest-cov", "pytest-randomly", "pytest-xdist", "pywinpty ; os_name == \"nt\"", "setuptools_scm[toml] (>=8.0,<9.0)"] +docs = ["ipykernel", "jupyter_client", "matplotlib", "nbconvert", "nbformat", "numpydoc", "pandas-datareader", "sphinx"] + [[package]] name = "terminado" version = "0.18.1" @@ -3889,6 +4725,18 @@ docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] +[[package]] +name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, +] + [[package]] name = "tinycss2" version = "1.4.0" @@ -3922,82 +4770,80 @@ files = [ [[package]] name = "tomli" -version = "2.4.0" +version = "2.4.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version == \"3.10\"" -files = [ - {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, - {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, - {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, - {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, - {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, - {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, - {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, - {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, - {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, - {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, - {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, - {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, - {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, - {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, - {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, - {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, - {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, - {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, - {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, - {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, - {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, - {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, - {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, - {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, - {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, - {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, - {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, - {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, - {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, - {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, - {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, - {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, - {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, - {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, - {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, - {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, - {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, - {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, - {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, - {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, - {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, - {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, - {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, - {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, - {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, - {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, - {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, +markers = "python_version < \"3.11\"" +files = [ + {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, + {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc"}, + {file = "tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049"}, + {file = "tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e"}, + {file = "tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1"}, + {file = "tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917"}, + {file = "tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9"}, + {file = "tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5"}, + {file = "tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd"}, + {file = "tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36"}, + {file = "tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba"}, + {file = "tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6"}, + {file = "tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7"}, + {file = "tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f"}, + {file = "tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8"}, + {file = "tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26"}, + {file = "tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396"}, + {file = "tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe"}, + {file = "tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f"}, ] [[package]] name = "tornado" -version = "6.5.4" +version = "6.5.5" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9"}, - {file = "tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843"}, - {file = "tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17"}, - {file = "tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335"}, - {file = "tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f"}, - {file = "tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84"}, - {file = "tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f"}, - {file = "tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8"}, - {file = "tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1"}, - {file = "tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc"}, - {file = "tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1"}, - {file = "tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7"}, + {file = "tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa"}, + {file = "tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521"}, + {file = "tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5"}, + {file = "tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07"}, + {file = "tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e"}, + {file = "tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca"}, + {file = "tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7"}, + {file = "tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b"}, + {file = "tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6"}, + {file = "tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9"}, ] [[package]] @@ -4024,19 +4870,19 @@ telegram = ["requests"] [[package]] name = "traitlets" -version = "5.14.3" +version = "5.15.0" description = "Traitlets Python configuration system" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, - {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, + {file = "traitlets-5.15.0-py3-none-any.whl", hash = "sha256:fb36a18867a6803deab09f3c5e0fa81bb7b26a5c9e82501c9933f759166eff40"}, + {file = "traitlets-5.15.0.tar.gz", hash = "sha256:4fead733f81cf1c4c938e06f8ca4633896833c9d89eff878159457f4d4392971"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "mypy (>=1.7.0,<1.19) ; platform_python_implementation == \"PyPy\"", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "typing-extensions" @@ -4044,7 +4890,7 @@ version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, @@ -4052,14 +4898,14 @@ files = [ [[package]] name = "tzdata" -version = "2025.3" +version = "2026.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main", "dev"] files = [ - {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, - {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, + {file = "tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7"}, + {file = "tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10"}, ] [[package]] @@ -4107,14 +4953,14 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.6.3" +version = "2.7.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.9" -groups = ["dev"] +python-versions = ">=3.10" +groups = ["main", "dev"] files = [ - {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, - {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, + {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, + {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, ] [package.extras] @@ -4125,14 +4971,14 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "wcwidth" -version = "0.6.0" +version = "0.7.0" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad"}, - {file = "wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159"}, + {file = "wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2"}, + {file = "wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0"}, ] [[package]] @@ -4188,7 +5034,166 @@ files = [ {file = "widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9"}, ] +[[package]] +name = "windio" +version = "2.1.1" +description = "Frameworks defining the inputs and outputs for systems engineering MDAO of wind turbine and plants." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "windio-2.1.1-py3-none-any.whl", hash = "sha256:333820957a0b38651d1ea48df5a2544f17d4cf766cee7bb2b1caed5557e7d35b"}, + {file = "windio-2.1.1.tar.gz", hash = "sha256:ca5581a8a54425695b7726713bbc878ad1f2073a767b568166fa1e8340ec7de9"}, +] + +[package.dependencies] +jsonschema = "*" +netcdf4 = "*" +"ruamel.yaml" = "*" +xarray = "*" + +[package.extras] +docs = ["gitpython", "json-schema-for-humans", "pydata-sphinx-theme", "sphinx (<=6.2)", "sphinx_multiversion"] +test = ["numpy", "pint", "pytest", "pytest-subtests", "scipy"] + +[[package]] +name = "wisdem" +version = "4.0.5" +description = "Wind-Plant Integrated System Design & Engineering Model" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "wisdem-4.0.5-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5334e38e26efba43c9848de4a4a4fc681b438635f0b773aff01ba6ed29d61833"}, + {file = "wisdem-4.0.5-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:8040476014ce81342a996dbb1b3355605a8fc0b824af7ea6d5b4a95735699895"}, + {file = "wisdem-4.0.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0e8749f4f3a81c3d3759451bf7c221e84165ec4c9c3200bf27d4250890b4caa1"}, + {file = "wisdem-4.0.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34cf7d3d26ab8fb56b447f6c3ad00697dfa1709a90059ae2ae724f4b15abbcc0"}, + {file = "wisdem-4.0.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fe5590a9a6bec0226944533930b8b2ecc088463464b1b89296612f548eeb1b3c"}, + {file = "wisdem-4.0.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:39fd308ddd7aa52f071eda69171c7eca09af9847d66072dd0e5036997056a3ec"}, + {file = "wisdem-4.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:6b53a9df4a08e4377066632a8b9030b193ad22725e3d2b220b4cc1b1a1443b95"}, + {file = "wisdem-4.0.5-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:74cd83d116e79dc2855866bab1e3b821e842bc589c682f5fea848a0cad645e0e"}, + {file = "wisdem-4.0.5-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:5d5b494a31f17c5160b0387a8fc23271813740276661b9587b8e596e286fa04b"}, + {file = "wisdem-4.0.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:225245e10812ae99532dc81ec51625188baf85e96bdd5ecd50f1b0df84f855cd"}, + {file = "wisdem-4.0.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47e531fa4caea3b17dd661bbcbc8e9ccb21a32ea8523d229345dfc594697d30e"}, + {file = "wisdem-4.0.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3fcfc81a86be6930bb1c361e1e98181c94dea921a9b082a55ab30257de66fe44"}, + {file = "wisdem-4.0.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a5e0042b9209857c92166b86428a2ece2f08a356a95b558df0558ba564a640a"}, + {file = "wisdem-4.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b9aab5fd74ed7f6f5d4ec019f21b4dc1396a1a8b6081c76b5ba696986cbd781"}, + {file = "wisdem-4.0.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:fd71cc4a9bf22b33b44a012b0fd93e07446cd873ef7dd51868026873d23d8e56"}, + {file = "wisdem-4.0.5-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:7ba8a539a7ea88226fbb88d7f3b85ce77fd9008baa86f2d70277a78b12d92df8"}, + {file = "wisdem-4.0.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b424a88bcaff9563edd58b6591428a0184f3f048505196780114680a436e28ca"}, + {file = "wisdem-4.0.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a80913729f90fccce7bcf0270a42410a93980a181878c23dfb998323a6cb4a7b"}, + {file = "wisdem-4.0.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b64dbc7f44a32a56c6af6579f18e57147fe50fa8d3f82e952693bcde5ed513d5"}, + {file = "wisdem-4.0.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:14b9080f1ed81c5484eee80902bb6135e19e35265154169cc01bda79a257ac2d"}, + {file = "wisdem-4.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:0ee7d2561072255c326787909a6b44e42a660e08a327682286874f19d20c03ff"}, + {file = "wisdem-4.0.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:399fdfb699dde9ecf2370ea70f11d2166f5576ff6f17924001a0091bb64d3ed9"}, + {file = "wisdem-4.0.5-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:aea2768334208adc94a98aebdfaac087ded95a2191b25889efc0e8111954e7c3"}, + {file = "wisdem-4.0.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c7eaa94675c5dfce17e66f808b492939d05da538943e26a26c764179682e44b"}, + {file = "wisdem-4.0.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e9dba0f90efb450a3b3d0d6bbde95efd9c55e3e56fde9102597199be0a5611"}, + {file = "wisdem-4.0.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:db7898d130fc3de7ddd25fe5a2f844e3ee58a6b5507b7b93fd8140518376c784"}, + {file = "wisdem-4.0.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:244a31cfc048c8089ab40662a34c98a4c05547e3ec692cb9722d9f0530a93cdd"}, + {file = "wisdem-4.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:d5816268c275139e0de18306e6b27d38ea73e9a3da8c3b719da00fdb4286bb7d"}, + {file = "wisdem-4.0.5-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:e3d78c2b617a4bac8de1bd42293effaabbb7fc7d0c11bd17e37a61f3a396f036"}, + {file = "wisdem-4.0.5-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:ed7ad36a201b4583a54b34ef84055f82c954bcd961edf80892217f6a0551a5a3"}, + {file = "wisdem-4.0.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b1ed6bd1db1bd5e00f997a8be19fb7bd1275603595d94b088bb23a30f45a4be"}, + {file = "wisdem-4.0.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dfab853f51bf4930cc809262c9bc9104d074dbf355103623f39be7b2a99b7506"}, + {file = "wisdem-4.0.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:114603f3b38e8c48bcf8489e9dbcd66c2ede51162ea0124f5942bb615e42b6d9"}, + {file = "wisdem-4.0.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:efb89da281fa9d4fd1282e83364ad63e1207fa0956ef7102dd2938ac7771ceb2"}, + {file = "wisdem-4.0.5-cp314-cp314-win_amd64.whl", hash = "sha256:b912a57ffb8206b8e635ab710d51d96429c8e06f139dd9733212576e0b2f5265"}, + {file = "wisdem-4.0.5-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:92d5843bd9065d0ee08e8fc43bc222246c9374d3cb7b41d82ab3cd2616273e0f"}, + {file = "wisdem-4.0.5-cp314-cp314t-macosx_15_0_arm64.whl", hash = "sha256:64df7bd76d79e7cd412308f615c21c287cd2cb3842abde7412d0355d1375d2af"}, + {file = "wisdem-4.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5870790fb8d44535db0b8e50195f4352fe050be95163026f2337e5bfc5170bd2"}, + {file = "wisdem-4.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c26d49792394ab6ff7d4a85c808b94641ee5fdc5e8d9732c4ef20342f1a140f1"}, + {file = "wisdem-4.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c946c169d7bd679ad7b7c89d81c58735e3bff3d79a848d3c27b2d6aa1787bc96"}, + {file = "wisdem-4.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9ebd315b7f4dbd93acaef36470ea7a303df02484866b5904fa0a5040729baf1a"}, + {file = "wisdem-4.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:1198f91fb5c8964bda81bda1cd6c161350536679bd03fb41166ecacd865564fe"}, + {file = "wisdem-4.0.5-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:035e242eb82b0cbf80497d487afb49d92474a96627a59684682eea479f703007"}, + {file = "wisdem-4.0.5-cp39-cp39-macosx_15_0_arm64.whl", hash = "sha256:fd68a77551832707d9ab2c5f7b5adbcb1826b5c9c1bc6baf766fc86d43da39a2"}, + {file = "wisdem-4.0.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77f39e9e9d934d6ecd0aa46772b174c493f58f8c1ef95d15e978d1909e5b26ce"}, + {file = "wisdem-4.0.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:38a812b5bcd165ee9ccbc5b9cdcc11903488fcc5faaac043ac45867def1e4d57"}, + {file = "wisdem-4.0.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ec75b435f752a7de52acb2ad25eb750593e1dab8f704fae06d772923d6033017"}, + {file = "wisdem-4.0.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:fde662130fa928552cbe0e8a28ccb87bc066c497d50be12b52dee40bf1b15a49"}, + {file = "wisdem-4.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:441662d687e55bb0417ed73b75c6d2b63ce0f6a10d889d4a2a1a50c90e441685"}, + {file = "wisdem-4.0.5.tar.gz", hash = "sha256:2361912b9816d02f71bbe5f5852bc434d4f3d606821ecfb345c2254711081019"}, +] + +[package.dependencies] +jsonmerge = "*" +jsonschema = "*" +moorpy = ">=1.2" +numpy = "*" +openmdao = "*" +openpyxl = "*" +orbit-nrel = ">=1.2.1" +pandas = "*" +pydoe3 = "*" +pyyaml = "*" +scipy = "*" +sortedcontainers = "*" +statsmodels = ">=0.14.5" +windIO = "*" + +[package.extras] +dev = ["black", "isort", "meson", "ninja", "pre-commit", "swig"] +docs = ["numpydoc", "sphinx", "sphinx-copybutton", "sphinx-jsonschema", "sphinx_rtd_theme (>=1.3)", "sphinxcontrib-bibtex"] +gui = ["dearpygui"] +opt = ["nlopt", "pyoptsparse"] +test = ["coveralls", "pytest", "pytest-cov"] + +[[package]] +name = "xarray" +version = "2025.6.1" +description = "N-D labeled arrays and datasets in Python" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version < \"3.11\"" +files = [ + {file = "xarray-2025.6.1-py3-none-any.whl", hash = "sha256:8b988b47f67a383bdc3b04c5db475cd165e580134c1f1943d52aee4a9c97651b"}, + {file = "xarray-2025.6.1.tar.gz", hash = "sha256:a84f3f07544634a130d7dc615ae44175419f4c77957a7255161ed99c69c7c8b0"}, +] + +[package.dependencies] +numpy = ">=1.24" +packaging = ">=23.2" +pandas = ">=2.1" + +[package.extras] +accel = ["bottleneck", "flox", "numba (>=0.54)", "numbagg", "opt_einsum", "scipy"] +complete = ["xarray[accel,etc,io,parallel,viz]"] +etc = ["sparse"] +io = ["cftime", "fsspec", "h5netcdf", "netCDF4", "pooch", "pydap ; python_version < \"3.10\"", "scipy", "zarr"] +parallel = ["dask[complete]"] +types = ["pandas-stubs", "scipy-stubs", "types-PyYAML", "types-Pygments", "types-colorama", "types-decorator", "types-defusedxml", "types-docutils", "types-networkx", "types-openpyxl", "types-pexpect", "types-psutil", "types-pycurl", "types-python-dateutil", "types-pytz", "types-setuptools"] +viz = ["cartopy", "matplotlib", "nc-time-axis", "seaborn"] + +[[package]] +name = "xarray" +version = "2026.4.0" +description = "N-D labeled arrays and datasets in Python" +optional = false +python-versions = ">=3.11" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "xarray-2026.4.0-py3-none-any.whl", hash = "sha256:d43751d9fb4a90f9249c30431684f00c41bc874f1edccd862631a40cbc0edf08"}, + {file = "xarray-2026.4.0.tar.gz", hash = "sha256:c4ac9a01a945d90d5b1628e2af045099a9d4943536d4f2ee3ae963c3b222d15b"}, +] + +[package.dependencies] +numpy = ">=1.26" +packaging = ">=24.2" +pandas = ">=2.2" + +[package.extras] +accel = ["bottleneck", "flox (>=0.10)", "numba (>=0.62)", "numbagg (>=0.9)", "opt_einsum", "scipy (>=1.15)"] +complete = ["xarray[accel,etc,io,parallel,viz]"] +etc = ["sparse (>=0.15)"] +io = ["cftime", "fsspec", "h5netcdf[h5py] (>=1.5.0)", "netCDF4 (>=1.6.0)", "pooch", "pydap", "scipy (>=1.15)", "zarr (>=3.0)"] +parallel = ["dask[complete]"] +types = ["pandas-stubs", "scipy-stubs", "types-PyYAML", "types-Pygments", "types-colorama", "types-decorator", "types-defusedxml", "types-docutils", "types-networkx", "types-openpyxl", "types-pexpect", "types-psutil", "types-pycurl", "types-python-dateutil", "types-pytz", "types-requests", "types-setuptools", "types-xlrd"] +viz = ["cartopy (>=0.24)", "matplotlib (>=3.10)", "nc-time-axis", "seaborn"] + [metadata] lock-version = "2.1" -python-versions = ">=3.10, <3.15" -content-hash = "0577e837066a12dcfc7e702c1fac22c2f7ffef58e19c837dc1fc791637a2b19e" +python-versions = ">3.10, <3.15" +content-hash = "ae0c7b5bdc2f44283a04806227b91505cd6c53e4aca09b45b1cac9c65ad36060" diff --git a/pyproject.toml b/pyproject.toml index 8eb55b0..d5c736c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,12 +7,13 @@ readme = "README.md" packages = [{ include = "MITRotor" }] [tool.poetry.dependencies] -python = ">=3.10, <3.15" +python = ">3.10, <3.15" numpy = "^2.2.1" scipy = ">=1.6" unified-momentum-model = {git = "https://github.com/Howland-Lab/Unified-Momentum-Model.git"} pyyaml = "^6.0.1" floris = {git = "https://github.com/misi9170/floris.git", branch = "feature/user-def-op-mod"} +rosco = "^2.10.4" [tool.poetry.group.dev.dependencies] black = { extras = ["jupyter"], version = "^23.9.1" } From 21cf7a2960b1e0007a01bd59c99af5adf56d88a9 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Tue, 2 Jun 2026 10:47:29 -0400 Subject: [PATCH 21/50] Working ROSCO controls in FLORIS --- MITRotor/FlorisInterface/FlorisInterface.py | 11 +- MITRotor/FlorisInterface/ROSCOInterface.py | 5 +- examples/example_08_floris_rosco.py | 273 +++++++++++++++----- poetry.lock | 2 +- pyproject.toml | 1 + 5 files changed, 222 insertions(+), 70 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 22baaad..73c0f27 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -30,7 +30,7 @@ def default_pitch_interp(): pitch_file = os.path.join(module_dir, "IEA_15mw_rotor.csv") df = pl.read_csv(pitch_file) wind_table = df["Wind [m/s]"].to_numpy() - pitch_table = df["Pitch [deg]"].to_numpy() + pitch_table = np.deg2rad(df["Pitch [deg]"]) # TODO: should fill_value be extrapolate? return interp1d(wind_table, pitch_table, kind="linear", fill_value="extrapolate", bounds_error=False) @@ -67,8 +67,9 @@ class MITRotorTurbine(BaseOperationModel): bem_model = field(init = True, factory = default_bem_factory, type = BEM) # create interp objects based on pitch and tsr csvs - pitch_interp = field(init=True, factory=default_pitch_interp, type = interp1d, repr = False) - tsr_interp = field(init=True, factory=default_tsr_interp, type = interp1d, repr = False) + pitch_interp = field(init = True, factory = default_pitch_interp, type = interp1d, repr = False) + pitch_rad = field(init = True, default=True, type = bool) + tsr_interp = field(init = True, factory = default_tsr_interp, type = interp1d, repr = False) # save most recent solution by unique floris arguments _last_key = field(init=False, default=None, type = bytes) @@ -113,7 +114,9 @@ def _update_solution(self, # get setpoints yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) - pitch = np.deg2rad(self.pitch_interp(rotor_average_velocities)) + pitch = self.pitch_interp(rotor_average_velocities) + if not self.pitch_rad: + pitch = np.deg2rad(pitch) tsr = self.tsr_interp(rotor_average_velocities) for tindex in range(n_turbines): # solve BEM diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index bc4be55..1f84783 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -85,7 +85,10 @@ def load_from_mitrotor( turbine.Cq = ROSCO_turbine.RotorPerformance(turbine.Cq_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) return turbine -def get_rosco_control_interps(rosco_yaml, bem, TurbineName = None, generator_inertia = None, GenEff = None): +def get_rosco_control_interps( + rosco_yaml, bem, + TurbineName = "IEA15MW", GenEff = 95.756, generator_inertia = 1836784, +): """ Creates pitch and tsr 1D interpolators using ROSCO controller tuning. diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 4707ecb..3b13758 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -1,83 +1,228 @@ # Python modules -import matplotlib.pyplot as plt -import os +import os +import matplotlib.pyplot as plt +import tempfile +from pathlib import Path +from ruamel.yaml import YAML +import numpy as np +import pandas as pd +import polars as pl +from scipy.interpolate import interp1d + +# FLORIS modules +from floris import FlorisModel, TimeSeries + # ROSCO toolbox modules from rosco.toolbox import controller as ROSCO_controller from rosco.toolbox import turbine as ROSCO_turbine -from rosco.toolbox.utilities import write_DISCON from rosco.toolbox.inputs.validation import load_rosco_yaml -from rosco.toolbox.utilities import write_rotor_performance + +# MITRotor modules +from MITRotor.Momentum import UnifiedMomentumLUT +from MITRotor import BEM, BEMGeometry, IEA15MW +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp +from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps + +figdir = Path("fig") + +def change_control_param(param_key, param_value, template_yaml, bem): + yaml = YAML() + with tempfile.TemporaryDirectory() as tmpdir: + temp_yaml = Path(tmpdir) / "rosco_temp.yaml" + + with open(template_yaml) as f: + data = yaml.load(f) + + data["controller_params"][param_key] = param_value + + with open(temp_yaml, "w") as f: + yaml.dump(data, f) + + pitch_interp, tsr_interp = get_rosco_control_interps(temp_yaml, bem) + return pitch_interp, tsr_interp + +def get_turbine_power_coefficent(bem, fmodel, wind_speeds): + rotor_area = np.pi * bem.rotor.R**2 + floris_power = np.squeeze(fmodel.get_turbine_powers()) + floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) + return floris_Cp def main(): - from MITRotor.Momentum import UnifiedMomentumLUT - from MITRotor import BEM, BEMGeometry, NREL5MW, IEA15MW, IEA10MW - from pathlib import Path - import pandas as pd - - # load CSVs - pitch_15 = pd.read_csv("examples/Tune_Cases/IEA15_pitch.csv") - tsr_15 = pd.read_csv("examples/Tune_Cases/IEA15_TSR.csv") - pitch_5 = pd.read_csv("examples/Tune_Cases/NLR5_pitch.csv") - tsr_5 = pd.read_csv("examples/Tune_Cases/NLR5_TSR.csv") - - # calcualte new + # wind condtions + wind_speeds = np.linspace(3, 25, 25) + wind_dirs = np.full_like(wind_speeds, 270.0) + turbulence_intensity = np.zeros_like(wind_speeds) + time_series = TimeSeries( + wind_speeds=wind_speeds, + wind_directions=wind_dirs, + turbulence_intensities=turbulence_intensity, + ) + + # load example trajectories from ROSCO Paper Figure 2: + # Abbas, N. J., Zalkind, D. S., Pao, L., & Wright, A. (2022). + # A reference open-source controller for fixed and floating offshore wind turbines. + # Wind Energy Science, 7(1), 53-73. + abbas_pitch = pd.read_csv("examples/examples_in/IEA15_pitch.csv") # note that this is in degrees + abbas_tsr = pd.read_csv("examples/examples_in/IEA15_TSR.csv") + abbas_pitch_interp = interp1d(abbas_pitch["x"], abbas_pitch["y"], kind="linear", fill_value="extrapolate", bounds_error=False) + abbas_tsr_interp = interp1d(abbas_tsr["x"], abbas_tsr["y"], kind="linear", fill_value="extrapolate", bounds_error=False) + + # create new MITRotor BEM model with a LUT for UMM cache_dir = Path("cache") cache_dir.mkdir(exist_ok=True, parents=True) cache_file = cache_dir / "lut.csv" - - # TODO: right now we are using 2 input files that have some shared parameters... - Nr, Ntheta = 10, 20 lut_model = UnifiedMomentumLUT( cache_fn=cache_file, regenerate=False, LUT_Cts=np.linspace(-0.5,1.5,40), LUT_yaws=np.linspace(0.0,20.1,20), ) - # NLR 5MW - inps_5 = load_rosco_yaml("examples/Tune_Cases/NLR_5MW.yaml") - turbine_params_5 = inps_5['turbine_params'] - controller_params_5 = inps_5['controller_params'] - rotor_5 = NREL5MW() - lut_bem_5 = BEM(rotor=rotor_5, momentum_model=lut_model, geometry = BEMGeometry(Nr=Nr, Ntheta=Ntheta)) - turbine_5 = ROSCO_turbine.Turbine(turbine_params_5) - turbine_5 = load_from_mitrotor(turbine_5, lut_bem_5, generator_inertia=534.116, GenEff=94.4) - controller_5 = ROSCO_controller.Controller(controller_params_5) - controller_5.tune_controller(turbine_5) - - - # IEA 15MW - inps_15 = load_rosco_yaml("examples/Tune_Cases/IEA15MW.yaml") - turbine_params_15 = inps_15['turbine_params'] - controller_params_15 = inps_15['controller_params'] - rotor_15 = IEA15MW() - lut_bem_15 = BEM(rotor=rotor_15, momentum_model=lut_model, geometry = BEMGeometry(Nr=Nr, Ntheta=Ntheta)) - turbine_15 = ROSCO_turbine.Turbine(turbine_params_15) - turbine_15 = load_from_mitrotor(turbine_15, lut_bem_15) - controller_15 = ROSCO_controller.Controller(controller_params_15) - controller_15.tune_controller(turbine_15) - - - plt.figure() - plt.plot(pitch_5["x"], pitch_5["y"], label = "NLR 5MW (Abbas et al.)", linestyle = "dashed") - plt.plot(pitch_15["x"], pitch_15["y"], label = "IEA 15MW (Abbas et al.)", linestyle = "dashed") - plt.plot(controller_5.v, np.rad2deg(np.maximum(controller_5.pitch_op, controller_5.ps_min_bld_pitch)), label='NLR 5MW (Generated)') - plt.plot(controller_15.v, np.rad2deg(np.maximum(controller_15.pitch_op, controller_15.ps_min_bld_pitch)), label='IEA 15MW (Generated)') - plt.xlabel('Wind Speed (m/s)') - plt.ylabel('Pitch') - plt.legend() - plt.grid(True) - plt.show() - - plt.figure() - plt.plot(tsr_5["x"], tsr_5["y"], label = "NLR 5MW (Abbas et al.)", linestyle = "dashed") - plt.plot(tsr_15["x"], tsr_15["y"], label = "IEA 15MW (Abbas et al.)", linestyle = "dashed") - plt.plot(controller_5.v, controller_5.TSR_op, label='NLR 5MW (Generated)') - plt.plot(controller_15.v, controller_15.TSR_op, label='IEA 15MW (Generated)') - plt.xlabel('Wind Speed (m/s)') - plt.ylabel('TSR') - plt.legend() - plt.grid(True) - plt.show() + bem = BEM(rotor = IEA15MW(), momentum_model = lut_model, geometry = BEMGeometry(Nr=10, Ntheta=20)) + + # Load IEA15MW ROSCO parameters to make controllers + rosco_yaml_PS_Mode_3 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" + rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp = get_rosco_control_interps(rosco_yaml_PS_Mode_3, bem) + rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp = change_control_param("PS_Mode", 0, rosco_yaml_PS_Mode_3, bem) + + # Plot IEA15MW control from ROSCO paper, ROSOC control with PS_Mode = 3, and ROSOC control with PS_Mode = 0 + pitch_abbas = abbas_pitch_interp(wind_speeds) + pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) + pitch_ps3 = np.rad2deg(rosco_PS_Mode_3_pitch_interp(wind_speeds)) + + tsr_abbas = abbas_tsr_interp(wind_speeds) + tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) + tsr_ps3 = rosco_PS_Mode_3_tsr_interp(wind_speeds) + + # Create figure + fig, ax = plt.subplots(1, 2, figsize=(10, 4), constrained_layout=True) + + # Plot pitch + ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) + ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") + ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") + + ax[0].set_xlabel("Wind Speed [m/s]") + ax[0].set_ylabel("Pitch [deg]") + ax[0].set_title("Pitch Schedule") + ax[0].grid(True) + ax[0].legend() + + # Plot TSR + ax[1].plot(wind_speeds, tsr_ps0, label="ROSCO: PS_Mode = 0", lw=3) + ax[1].plot(wind_speeds, tsr_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") + ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") + + ax[1].set_xlabel("Wind Speed [m/s]") + ax[1].set_ylabel("TSR [-]") + ax[1].set_title("Tip-Speed Ratio (TSR) Schedule") + ax[1].grid(True) + ax[1].legend() + + plt.savefig(figdir / "example_8_IEA15mw_controls.png", dpi=300) + + # make FLORIS turbines + floris_default_turbine = MITRotorTurbine( + bem_model = bem, + ) + + floris_abbas_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = abbas_pitch_interp, + pitch_rad = False, + tsr_interp = abbas_tsr_interp, + ) + + floris_PS_Mode_0_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = rosco_PS_Mode_0_pitch_interp, + pitch_rad = True, + tsr_interp = rosco_PS_Mode_0_tsr_interp, + ) + + floris_PS_Mode_3_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = rosco_PS_Mode_3_pitch_interp, + pitch_rad = True, + tsr_interp = rosco_PS_Mode_3_tsr_interp, + ) + + fmodel_default = FlorisModel("defaults") + fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_default.set_operation_model(floris_default_turbine) + fmodel_default.run() + Ct_default = fmodel_default.get_turbine_thrust_coefficients() + Cp_default = get_turbine_power_coefficent(bem, fmodel_default, wind_speeds) + + fmodel_abbas = FlorisModel("defaults") + fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_abbas.set_operation_model(floris_abbas_turbine) + fmodel_abbas.run() + Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() + Cp_abbas = get_turbine_power_coefficent(bem, fmodel_abbas, wind_speeds) + + fmodel_PS_Mode_0 = FlorisModel("defaults") + fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) + fmodel_PS_Mode_0.run() + Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() + Cp_PS_Mode_0 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_0, wind_speeds) + + fmodel_PS_Mode_3 = FlorisModel("defaults") + fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) + fmodel_PS_Mode_3.run() + Ct_PS_Mode_3 = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() + Cp_PS_Mode_3 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) + + # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) + fig, (ax1, ax2) = plt.subplots(ncols = 2, sharey = True, figsize = (12, 6)) + ax1.plot( + wind_speeds, Ct_default, label="Default Control", + linewidth=2, linestyle = "solid", zorder = 1, + ) + ax1.plot( + wind_speeds, Ct_abbas, label="Abbas et al. Control", + linewidth=2, linestyle = "solid", zorder = 1, + ) + ax1.plot( + wind_speeds, Ct_PS_Mode_0, label="ROSCO PS_Mode = 0", + linewidth=2, linestyle = "dashed", zorder = 1, + ) + ax1.plot(wind_speeds, Ct_PS_Mode_3, label="ROSCO PS_Mode = 3", + linewidth=2, linestyle = "dotted", zorder = 1, + ) + ax1.set_xlabel("Wind Speed [m/s]") + ax1.set_ylabel("$C_T$") + ax1.tick_params() + ax1.set_title("$C_T$") + ax1.grid(True) + ax1.legend() + + ax2.plot( + wind_speeds, Cp_default, label="Default Control", + linewidth=2, linestyle = "solid", zorder = 1, + ) + ax2.plot( + wind_speeds, Cp_abbas, label="Abbas et al. Control", + linewidth=2, linestyle = "solid", zorder = 1, + ) + ax2.plot( + wind_speeds, Cp_PS_Mode_0, label="ROSCO PS_Mode = 0", + linewidth=2, linestyle = "dashed", zorder = 1, + ) + ax2.plot(wind_speeds, Cp_PS_Mode_3, label="ROSCO PS_Mode = 3", + linewidth=2, linestyle = "dotted", zorder = 1, + ) + ax2.set_xlabel("Wind Speed [m/s]") + ax2.set_ylabel("$C_P$") + ax2.tick_params() + ax2.set_title("$C_P$") + ax2.grid(True) + ax2.legend() + + plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) + + if __name__ == "__main__": main() \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 8760fae..acd7f3c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -5196,4 +5196,4 @@ viz = ["cartopy (>=0.24)", "matplotlib (>=3.10)", "nc-time-axis", "seaborn"] [metadata] lock-version = "2.1" python-versions = ">3.10, <3.15" -content-hash = "ae0c7b5bdc2f44283a04806227b91505cd6c53e4aca09b45b1cac9c65ad36060" +content-hash = "61f7d0b43670dfa0ac04404950bbd30671629fa95a5f30ba89114c20c7608fb5" diff --git a/pyproject.toml b/pyproject.toml index d5c736c..05c7269 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ unified-momentum-model = {git = "https://github.com/Howland-Lab/Unified-Momentum pyyaml = "^6.0.1" floris = {git = "https://github.com/misi9170/floris.git", branch = "feature/user-def-op-mod"} rosco = "^2.10.4" +ruamel-yaml = "^0.19.1" [tool.poetry.group.dev.dependencies] black = { extras = ["jupyter"], version = "^23.9.1" } From 178acb70b08380c62f7ebc1f582547addf1d31f6 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Tue, 2 Jun 2026 11:53:32 -0400 Subject: [PATCH 22/50] Yaw and deg vs rad bugs fixed --- MITRotor/FlorisInterface/FlorisInterface.py | 9 +- examples/example_06_floris_integration.py | 9 +- examples/example_08_floris_rosco.py | 98 ++++++++++++++------- 3 files changed, 73 insertions(+), 43 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 73c0f27..a8182f1 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -68,7 +68,7 @@ class MITRotorTurbine(BaseOperationModel): # create interp objects based on pitch and tsr csvs pitch_interp = field(init = True, factory = default_pitch_interp, type = interp1d, repr = False) - pitch_rad = field(init = True, default=True, type = bool) + pitch_rad = field(init = True, default = True, type = bool) tsr_interp = field(init = True, factory = default_tsr_interp, type = interp1d, repr = False) # save most recent solution by unique floris arguments @@ -114,10 +114,11 @@ def _update_solution(self, # get setpoints yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) - pitch = self.pitch_interp(rotor_average_velocities) + rotor_normal_average_velocities = np.cos(yaw) * np.cos(tilt) * rotor_average_velocities + pitch = self.pitch_interp(rotor_normal_average_velocities) if not self.pitch_rad: pitch = np.deg2rad(pitch) - tsr = self.tsr_interp(rotor_average_velocities) + tsr = self.tsr_interp(rotor_normal_average_velocities) for tindex in range(n_turbines): # solve BEM bem_sol = self.bem_model(pitch[:, tindex], tsr[:, tindex], yaw = yaw[:, tindex], tilt = tilt[:, tindex]) @@ -125,7 +126,7 @@ def _update_solution(self, self._a[:, tindex] = bem_sol.a() self._Ct[:, tindex] = bem_sol.Ct() # compute power - self._power[:, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_average_velocities[:, tindex])**3 + self._power[:, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_normal_average_velocities[:, tindex])**3 return def power(self, **kwargs) -> NDArrayFloat: diff --git a/examples/example_06_floris_integration.py b/examples/example_06_floris_integration.py index e65bf3a..78d6e7b 100644 --- a/examples/example_06_floris_integration.py +++ b/examples/example_06_floris_integration.py @@ -73,7 +73,7 @@ fig, ax = plt.subplots(figsize=(8, 6)) ax.scatter( wind_speeds, - pitches, + np.rad2deg(pitches), s=40, edgecolors="k", label = "Interpolated Pitch [deg]" @@ -104,13 +104,12 @@ # -------- plot CT and CP values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) ------- # solve UMM-BEM though MITRotor - rotor averaged -pitches_rad = np.deg2rad(pitches) bem_rotor_umm = default_bem_factory() mit_rotor_umm_start = time.time() -pitches = np.deg2rad(pitch_interp(wind_speeds)) +pitches_rad = pitch_interp(wind_speeds) tsrs = tsr_interp(wind_speeds) -yaws, tilts = np.zeros_like(pitches), np.zeros_like(pitches) -mit_sols_rotor_umm = bem_rotor_umm(pitch=pitches, tsr=tsrs, yaw=yaws, tilt=tilts) +yaws, tilts = np.zeros_like(pitches_rad), np.zeros_like(pitches_rad) +mit_sols_rotor_umm = bem_rotor_umm(pitch=pitches_rad, tsr=tsrs, yaw=yaws, tilt=tilts) mit_rotor_umm_end = time.time() mit_Ct_rotor_umm = mit_sols_rotor_umm.Ct() mit_Cp_rotor_umm = mit_sols_rotor_umm.Cp() diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 3b13758..3c0835a 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -73,9 +73,9 @@ def main(): cache_file = cache_dir / "lut.csv" lut_model = UnifiedMomentumLUT( cache_fn=cache_file, - regenerate=False, + regenerate=True, LUT_Cts=np.linspace(-0.5,1.5,40), - LUT_yaws=np.linspace(0.0,20.1,20), + LUT_yaws=np.linspace(0.0,25.1,25), ) bem = BEM(rotor = IEA15MW(), momentum_model = lut_model, geometry = BEMGeometry(Nr=10, Ntheta=20)) @@ -94,8 +94,8 @@ def main(): tsr_ps3 = rosco_PS_Mode_3_tsr_interp(wind_speeds) # Create figure - fig, ax = plt.subplots(1, 2, figsize=(10, 4), constrained_layout=True) - + fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) + fig.suptitle(fr"Setpoint Trajectories") # Plot pitch ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") @@ -105,12 +105,12 @@ def main(): ax[0].set_ylabel("Pitch [deg]") ax[0].set_title("Pitch Schedule") ax[0].grid(True) - ax[0].legend() + # ax[0].legend() # Plot TSR - ax[1].plot(wind_speeds, tsr_ps0, label="ROSCO: PS_Mode = 0", lw=3) - ax[1].plot(wind_speeds, tsr_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") - ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") + ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) + ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") + ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") ax[1].set_xlabel("Wind Speed [m/s]") ax[1].set_ylabel("TSR [-]") @@ -145,84 +145,114 @@ def main(): pitch_rad = True, tsr_interp = rosco_PS_Mode_3_tsr_interp, ) - + yaw = 0.0 # degrees + yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] fmodel_default = FlorisModel("defaults") - fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_default.set_operation_model(floris_default_turbine) fmodel_default.run() Ct_default = fmodel_default.get_turbine_thrust_coefficients() Cp_default = get_turbine_power_coefficent(bem, fmodel_default, wind_speeds) fmodel_abbas = FlorisModel("defaults") - fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_abbas.set_operation_model(floris_abbas_turbine) fmodel_abbas.run() Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() Cp_abbas = get_turbine_power_coefficent(bem, fmodel_abbas, wind_speeds) fmodel_PS_Mode_0 = FlorisModel("defaults") - fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) fmodel_PS_Mode_0.run() Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() Cp_PS_Mode_0 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_0, wind_speeds) fmodel_PS_Mode_3 = FlorisModel("defaults") - fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) fmodel_PS_Mode_3.run() Ct_PS_Mode_3 = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() Cp_PS_Mode_3 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) - # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nrel.gov/docs/fy20osti/75698.pdf) - fig, (ax1, ax2) = plt.subplots(ncols = 2, sharey = True, figsize = (12, 6)) + # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) + fig, (ax1, ax2) = plt.subplots(ncols = 2, sharey = True, figsize = (10,4), constrained_layout=True) + fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = 0 for Different Control Strategies") ax1.plot( - wind_speeds, Ct_default, label="Default Control", - linewidth=2, linestyle = "solid", zorder = 1, + wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", + lw=3, linestyle = "solid", zorder = 1, ) ax1.plot( - wind_speeds, Ct_abbas, label="Abbas et al. Control", - linewidth=2, linestyle = "solid", zorder = 1, + wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", + lw=3, linestyle = "solid", zorder = 1, ) ax1.plot( - wind_speeds, Ct_PS_Mode_0, label="ROSCO PS_Mode = 0", - linewidth=2, linestyle = "dashed", zorder = 1, + wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, ) - ax1.plot(wind_speeds, Ct_PS_Mode_3, label="ROSCO PS_Mode = 3", - linewidth=2, linestyle = "dotted", zorder = 1, + ax1.plot(wind_speeds, Ct_PS_Mode_3, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 3", + lw=3, linestyle = "dotted", zorder = 1, ) ax1.set_xlabel("Wind Speed [m/s]") ax1.set_ylabel("$C_T$") - ax1.tick_params() ax1.set_title("$C_T$") ax1.grid(True) - ax1.legend() + # ax1.legend() ax2.plot( - wind_speeds, Cp_default, label="Default Control", - linewidth=2, linestyle = "solid", zorder = 1, + wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", + lw=3, linestyle = "solid", zorder = 1, ) ax2.plot( - wind_speeds, Cp_abbas, label="Abbas et al. Control", - linewidth=2, linestyle = "solid", zorder = 1, + wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", + lw=3, linestyle = "solid", zorder = 1, ) ax2.plot( - wind_speeds, Cp_PS_Mode_0, label="ROSCO PS_Mode = 0", - linewidth=2, linestyle = "dashed", zorder = 1, + wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, ) - ax2.plot(wind_speeds, Cp_PS_Mode_3, label="ROSCO PS_Mode = 3", - linewidth=2, linestyle = "dotted", zorder = 1, + ax2.plot(wind_speeds, Cp_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", + lw=3, linestyle = "dotted", zorder = 1, ) ax2.set_xlabel("Wind Speed [m/s]") ax2.set_ylabel("$C_P$") - ax2.tick_params() ax2.set_title("$C_P$") ax2.grid(True) ax2.legend() plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) + # plot the difference in CT/CP curves for different yaw values + yaw_list = [0.0, 10.0, 20.0] # degrees + fig, (ax1, ax2) = plt.subplots(ncols = 2, sharey = True, figsize = (10,4), constrained_layout=True) + fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: PS_Mode = 3") + for (i, yaw) in enumerate(yaw_list): + yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] + fmodel_PS_Mode_3 = FlorisModel("defaults") + fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) + fmodel_PS_Mode_3.run() + ct = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() + cp = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) + + ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + + ax1.set_xlabel("Wind Speed [m/s]") + ax1.set_ylabel("$C_T$") + ax1.set_title("$C_T$") + ax1.grid(True) + ax2.set_xlabel("Wind Speed [m/s]") + ax2.set_ylabel("$C_P$") + ax2.set_title("$C_P$") + ax2.grid(True) + ax2.legend() + plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) if __name__ == "__main__": main() \ No newline at end of file From 03c0b5c9835769233c4c67bf6d418a051e4f7bc7 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 4 Jun 2026 15:55:48 -0400 Subject: [PATCH 23/50] Attempt at debugging yaw difference --- MITRotor/FlorisInterface/FlorisInterface.py | 16 ++- examples/example_08_floris_rosco.py | 135 +++++++++++++++++--- 2 files changed, 131 insertions(+), 20 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index a8182f1..329f95d 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -8,6 +8,7 @@ from floris.type_dec import floris_float_type, NDArrayFloat from floris.core.turbine.operation_models import BaseOperationModel from floris.core.rotor_velocity import average_velocity +from floris.utilities import cosd # MITRotor / UMM Imports from MITRotor.ReferenceTurbines import IEA15MW from MITRotor.Momentum import UnifiedMomentum @@ -88,6 +89,7 @@ def _update_solution(self, tilt_angles: NDArrayFloat, average_method: str = "cubic-mean", cubature_weights: Optional[NDArrayFloat] = None, + power_thrust_table: Optional[dict] = None, **_, ): # create cache key for current inputs @@ -103,22 +105,28 @@ def _update_solution(self, self._power = np.empty((n_findex, n_turbines), dtype=floris_float_type) # compute the power-effective wind speed across the rotor - rotor_average_velocities = average_velocity( + rotor_average_velocities = average_velocity( # NOT adjusted for yaw velocities=velocities, method=average_method, cubature_weights=cubature_weights, ) - + # self.farm.cosine_loss_exponent_yaw + pW = power_thrust_table["cosine_loss_exponent_yaw"] / 3.0 + rotor_normal_average_velocities = rotor_average_velocities * (cosd(yaw_angles) ** pW) + # rotor_normal_average_velocities = rotor_average_velocities * cosd(yaw_angles) * cosd(tilt_angles) # calculate rotor area rotor_area = np.pi * self.bem_model.rotor.R**2 # get setpoints yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) - rotor_normal_average_velocities = np.cos(yaw) * np.cos(tilt) * rotor_average_velocities pitch = self.pitch_interp(rotor_normal_average_velocities) if not self.pitch_rad: pitch = np.deg2rad(pitch) tsr = self.tsr_interp(rotor_normal_average_velocities) + print(np.mean(yaw_angles)) + print(np.ravel(rotor_average_velocities)) + print(np.ravel(pitch)) + print(np.ravel(tsr)) for tindex in range(n_turbines): # solve BEM bem_sol = self.bem_model(pitch[:, tindex], tsr[:, tindex], yaw = yaw[:, tindex], tilt = tilt[:, tindex]) @@ -126,7 +134,7 @@ def _update_solution(self, self._a[:, tindex] = bem_sol.a() self._Ct[:, tindex] = bem_sol.Ct() # compute power - self._power[:, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_normal_average_velocities[:, tindex])**3 + self._power[:, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_average_velocities[:, tindex])**3 return def power(self, **kwargs) -> NDArrayFloat: diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 3c0835a..414ff08 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -45,7 +45,7 @@ def get_turbine_power_coefficent(bem, fmodel, wind_speeds): rotor_area = np.pi * bem.rotor.R**2 floris_power = np.squeeze(fmodel.get_turbine_powers()) floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) - return floris_Cp + return floris_Cp, floris_power def main(): # wind condtions @@ -67,7 +67,7 @@ def main(): abbas_pitch_interp = interp1d(abbas_pitch["x"], abbas_pitch["y"], kind="linear", fill_value="extrapolate", bounds_error=False) abbas_tsr_interp = interp1d(abbas_tsr["x"], abbas_tsr["y"], kind="linear", fill_value="extrapolate", bounds_error=False) - # create new MITRotor BEM model with a LUT for UMM + # # create new MITRotor BEM model with a LUT for UMM cache_dir = Path("cache") cache_dir.mkdir(exist_ok=True, parents=True) cache_file = cache_dir / "lut.csv" @@ -79,7 +79,7 @@ def main(): ) bem = BEM(rotor = IEA15MW(), momentum_model = lut_model, geometry = BEMGeometry(Nr=10, Ntheta=20)) - # Load IEA15MW ROSCO parameters to make controllers + # # Load IEA15MW ROSCO parameters to make controllers rosco_yaml_PS_Mode_3 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp = get_rosco_control_interps(rosco_yaml_PS_Mode_3, bem) rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp = change_control_param("PS_Mode", 0, rosco_yaml_PS_Mode_3, bem) @@ -152,31 +152,32 @@ def main(): fmodel_default.set_operation_model(floris_default_turbine) fmodel_default.run() Ct_default = fmodel_default.get_turbine_thrust_coefficients() - Cp_default = get_turbine_power_coefficent(bem, fmodel_default, wind_speeds) + Cp_default, P_default = get_turbine_power_coefficent(bem, fmodel_default, wind_speeds) fmodel_abbas = FlorisModel("defaults") fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_abbas.set_operation_model(floris_abbas_turbine) fmodel_abbas.run() Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() - Cp_abbas = get_turbine_power_coefficent(bem, fmodel_abbas, wind_speeds) + Cp_abbas, P_abbas = get_turbine_power_coefficent(bem, fmodel_abbas, wind_speeds) + fmodel_PS_Mode_0 = FlorisModel("defaults") fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) fmodel_PS_Mode_0.run() Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() - Cp_PS_Mode_0 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_0, wind_speeds) + Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_0, wind_speeds) fmodel_PS_Mode_3 = FlorisModel("defaults") fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) fmodel_PS_Mode_3.run() Ct_PS_Mode_3 = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() - Cp_PS_Mode_3 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) + Cp_PS_Mode_3, P_PS_Mode_3 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) - fig, (ax1, ax2) = plt.subplots(ncols = 2, sharey = True, figsize = (10,4), constrained_layout=True) + fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (15,4), constrained_layout=True) fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = 0 for Different Control Strategies") ax1.plot( wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", @@ -194,7 +195,7 @@ def main(): lw=3, linestyle = "dotted", zorder = 1, ) ax1.set_xlabel("Wind Speed [m/s]") - ax1.set_ylabel("$C_T$") + ax1.set_ylabel("$C_T [-]$") ax1.set_title("$C_T$") ax1.grid(True) # ax1.legend() @@ -215,16 +216,37 @@ def main(): lw=3, linestyle = "dotted", zorder = 1, ) ax2.set_xlabel("Wind Speed [m/s]") - ax2.set_ylabel("$C_P$") + ax2.set_ylabel("$C_P [-]$") ax2.set_title("$C_P$") ax2.grid(True) - ax2.legend() + # ax2.legend() + + ax3.plot( + wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot( + wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot( + wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, + ) + ax3.plot(wind_speeds, P_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", + lw=3, linestyle = "dotted", zorder = 1, + ) + ax3.set_xlabel("Wind Speed [m/s]") + ax3.set_ylabel("$Power [MW]$") + ax3.set_title("$Power$") + ax3.grid(True) + ax3.legend() plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) # plot the difference in CT/CP curves for different yaw values yaw_list = [0.0, 10.0, 20.0] # degrees - fig, (ax1, ax2) = plt.subplots(ncols = 2, sharey = True, figsize = (10,4), constrained_layout=True) + fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: PS_Mode = 3") for (i, yaw) in enumerate(yaw_list): yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] @@ -233,7 +255,7 @@ def main(): fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) fmodel_PS_Mode_3.run() ct = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() - cp = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) + cp, p = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", lw=3, linestyle = "solid", zorder = 1, @@ -241,18 +263,99 @@ def main(): ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", lw=3, linestyle = "solid", zorder = 1, ) + ax3.plot(wind_speeds, p, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) ax1.set_xlabel("Wind Speed [m/s]") - ax1.set_ylabel("$C_T$") + ax1.set_ylabel("$C_T [-]$") ax1.set_title("$C_T$") ax1.grid(True) ax2.set_xlabel("Wind Speed [m/s]") - ax2.set_ylabel("$C_P$") + ax2.set_ylabel("$C_P [-]$") ax2.set_title("$C_P$") ax2.grid(True) - ax2.legend() + + ax3.set_xlabel("Wind Speed [m/s]") + ax3.set_ylabel("$Power [MW]$") + ax3.set_title("$Power$") + ax3.grid(True) + ax3.legend() plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) + # VALUES FROM THE LAST YAW EXAMPLE + # yaw_angles = [0.0, 10.0, 20.0] + # wind_speeds = np.array([ 2.99013218, 3.90378368, 4.81743518, 5.73108668, 6.64473818, 7.55838968, + # 8.47204118, 9.38569268, 10.29934418, 11.21299568, 12.12664717, 13.04029867, + # 13.95395017, 14.86760167, 15.78125317, 16.69490467, 17.60855617, 18.52220767, + # 19.43585917, 20.34951067, 21.26316217, 22.17681367, 23.09046517, 24.00411667, + # 24.91776817]) + + # pitch_data = [ + # np.array([0.06674022, 0.05708731, 0.04527502, 0.02821344, 0.00638814, 0., + # 0., 0., 0.03561096, 0.06201665, 0.10170293, 0.14064172, + # 0.17480852, 0.20334416, 0.2279438, 0.24969219, 0.26945148, 0.28830328, + # 0.3064061, 0.32385969, 0.34076384, 0.35709961, 0.37304778, 0.38862888, + # 0.40381301]), + # np.array([0.0670117, 0.05749029, 0.04596395, 0.02940459, 0.00804692, 0., + # 0., 0., 0.03159737, 0.05959471, 0.09666413, 0.13512453, + # 0.17020744, 0.19918221, 0.22414017, 0.2461998, 0.26590456, 0.2847307, + # 0.30278677, 0.32017919, 0.33707697, 0.35336143, 0.3692476, 0.38476091, + # 0.39988875]), + # np.array([0.06782725, 0.05861179, 0.0480336, 0.03267438, 0.01290243, 0., + # 0., 0., 0.01790879, 0.05231887, 0.08152841, 0.11886783, + # 0.15571155, 0.18608686, 0.21210147, 0.23480731, 0.25495804, 0.27378792, + # 0.29175, 0.30904482, 0.32577372, 0.34195922, 0.35764598, 0.37297828, + # 0.38797132]) + # ] + + # tsr_data = [ + # np.array([21.17700633, 16.24293034, 13.15445983, 11.05613061, 9.53582497, 9., + # 9., 9., 9., 8.54102737, 7.89840549, 7.34547759, + # 6.86473567, 6.44293918, 6.06989257, 5.73761929, 5.43979028, 5.17132019, + # 4.92807656, 4.7066669, 4.50428035, 4.31856823, 4.14761354, 3.98985351, + # 3.84362968]), + # np.array([21.36151077, 16.39563759, 13.28451444, 11.1591271, 9.62802523, 9., + # 9., 9., 9., 8.62614707, 7.97636669, 7.41738871, + # 6.93146656, 6.50518492, 6.12821732, 5.79248716, 5.49158768, 5.22037222, + # 4.97523891, 4.7520206, 4.54791367, 4.36057184, 4.18801658, 4.02856807, + # 3.88079097]), + # np.array([21.91578937, 16.88295332, 13.67521769, 11.49774122, 9.91488218, 9.00015098, + # 9., 9., 9., 8.88185921, 8.21215035, 7.63791414, + # 7.13816236, 6.6993949, 6.31116194, 5.96525606, 5.65514567, 5.37646321, + # 5.12399624, 4.89401575, 4.6836678, 4.49055784, 4.31266275, 4.14835247, + # 3.99643498]) + # ] + + # # Create figure + # fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 5)) + + # # Colors for yaw angles + # colors = plt.cm.viridis(np.linspace(0, 1, len(yaw_angles))) + + # # Plot pitch vs wind speed + # for i, yaw in enumerate(yaw_angles): + # ax1.plot(wind_speeds, np.rad2deg(pitch_data[i]), marker='o', linewidth=2, + # label=f'Yaw = {yaw}°', color=colors[i]) + # ax1.set_xlabel('Wind Speed (m/s)', fontsize=12) + # ax1.set_ylabel('Pitch Angle (deg)', fontsize=12) + # ax1.set_title('Pitch vs Wind Speed', fontsize=13, fontweight='bold') + # ax1.legend() + # ax1.grid(True, alpha=0.3) + + # # Plot TSR vs wind speed + # for i, yaw in enumerate(yaw_angles): + # ax2.plot(wind_speeds, tsr_data[i], marker='s', linewidth=2, + # label=f'Yaw = {yaw}°', color=colors[i]) + # ax2.set_xlabel('Wind Speed (m/s)', fontsize=12) + # ax2.set_ylabel('Tip Speed Ratio', fontsize=12) + # ax2.set_title('TSR vs Wind Speed', fontsize=13, fontweight='bold') + # ax2.legend() + # ax2.grid(True, alpha=0.3) + + # plt.tight_layout() + # plt.savefig(figdir / "example_8_IEA15mw_setpoints_yawed.png", dpi=300) + if __name__ == "__main__": main() \ No newline at end of file From 5be3048cc6ce7a2ed5df99b81cc58fc1c7e5b529 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 4 Jun 2026 15:57:27 -0400 Subject: [PATCH 24/50] Add example CSVs --- .gitignore | 1 + examples/examples_in/IEA15_TSR.csv | 17 +++++++++++++++++ examples/examples_in/IEA15_pitch.csv | 19 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 examples/examples_in/IEA15_TSR.csv create mode 100644 examples/examples_in/IEA15_pitch.csv diff --git a/.gitignore b/.gitignore index 35206bb..475d7a6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ fig* # Allow these CSVs needed for the floris interface !MITRotor/FlorisInterface/IEA_15mw_rotor.csv +!examples/examples_in/* Validation/ diff --git a/examples/examples_in/IEA15_TSR.csv b/examples/examples_in/IEA15_TSR.csv new file mode 100644 index 0000000..0c9e459 --- /dev/null +++ b/examples/examples_in/IEA15_TSR.csv @@ -0,0 +1,17 @@ +x,y +3.0474198047419803, 20.782122905027933 +3.7726638772663876, 16.75977653631285 +4.609483960948396, 13.743016759776536 +5.557880055788005, 11.396648044692737 +6.95258019525802, 9.050279329608937 +8.737796373779638, 8.938547486033519 +10.132496513249652, 8.938547486033519 +11.192468619246862, 8.491620111731843 +12.838214783821478, 7.374301675977653 +15.0139470013947, 6.256983240223463 +16.715481171548117, 5.58659217877095 +18.11018131101813, 5.251396648044692 +19.393305439330543, 4.804469273743017 +21.15062761506276, 4.4692737430167595 +22.517433751743376, 4.134078212290502 +25.0278940027894, 3.6871508379888267 \ No newline at end of file diff --git a/examples/examples_in/IEA15_pitch.csv b/examples/examples_in/IEA15_pitch.csv new file mode 100644 index 0000000..920d988 --- /dev/null +++ b/examples/examples_in/IEA15_pitch.csv @@ -0,0 +1,19 @@ +x,y +2.99163179916318, 4.022346368715084 +4.191073919107392, 3.4636871508379885 +5.306834030683403, 2.346368715083799 +6.199442119944212, 1.1173184357541899 +7.00836820083682, 0.11173184357541899 +8.235704323570433, -0.11173184357541899 +9.435146443514643, -0.11173184357541899 +10.076708507670851, 1.5642458100558658 +10.774058577405857, 3.0167597765363126 +11.248256624825663, 3.5754189944134076 +12.168758716875871, 6.033519553072625 +13.312412831241284, 8.491620111731843 +15.0418410041841, 11.396648044692737 +16.743375174337515, 13.631284916201116 +18.668061366806135, 16.089385474860336 +20.955369595536958, 18.65921787709497 +23.13110181311018, 21.11731843575419 +25.0836820083682, 23.01675977653631 \ No newline at end of file From 7b96114e4c6e57a59a5bfb2b3902e234d64c1292 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 26 Jun 2026 15:50:42 -0400 Subject: [PATCH 25/50] Working version of stead-state ROSCO simulation code --- .gitignore | 5 +- MITRotor/FlorisInterface/FlorisInterface.py | 17 +- MITRotor/FlorisInterface/ROSCOInterface.py | 594 +++++++++++++++++- MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml | 2 +- examples/example_08_floris_rosco.py | 150 ++--- poetry.lock | 24 +- pyproject.toml | 1 + 7 files changed, 700 insertions(+), 93 deletions(-) diff --git a/.gitignore b/.gitignore index 475d7a6..e4e4eff 100644 --- a/.gitignore +++ b/.gitignore @@ -197,4 +197,7 @@ pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python .DS_Store -examples/Tune_Cases/ \ No newline at end of file +examples/Tune_Cases/ +*dbg* +DISCON.IN +*txt \ No newline at end of file diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 329f95d..b45fa79 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -71,6 +71,7 @@ class MITRotorTurbine(BaseOperationModel): pitch_interp = field(init = True, factory = default_pitch_interp, type = interp1d, repr = False) pitch_rad = field(init = True, default = True, type = bool) tsr_interp = field(init = True, factory = default_tsr_interp, type = interp1d, repr = False) + rated_rotor_speed = field(init=True, default=None, type=Optional[float]) # rad/s # save most recent solution by unique floris arguments _last_key = field(init=False, default=None, type = bytes) @@ -122,11 +123,17 @@ def _update_solution(self, pitch = self.pitch_interp(rotor_normal_average_velocities) if not self.pitch_rad: pitch = np.deg2rad(pitch) - tsr = self.tsr_interp(rotor_normal_average_velocities) - print(np.mean(yaw_angles)) - print(np.ravel(rotor_average_velocities)) - print(np.ravel(pitch)) - print(np.ravel(tsr)) + + if self.rated_rotor_speed is None: + tsr = self.tsr_interp(rotor_normal_average_velocities) + else: + R = self.bem_model.rotor.R + tsr_lookup = self.tsr_interp(rotor_normal_average_velocities) + omega_lookup = tsr_lookup * rotor_normal_average_velocities / R # rad/s implied by lookup + tsr_from_rated_speed = self.rated_rotor_speed * R / rotor_average_velocities # above-rated branch + tsr = np.where(omega_lookup <= self.rated_rotor_speed, tsr_lookup, tsr_from_rated_speed) + tsr = np.maximum(tsr, 0.0) + for tindex in range(n_turbines): # solve BEM bem_sol = self.bem_model(pitch[:, tindex], tsr[:, tindex], yaw = yaw[:, tindex], tilt = tilt[:, tindex]) diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 1f84783..45e1fd0 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -1,13 +1,28 @@ +# Python modules +import os import numpy as np from scipy.interpolate import interp1d - +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D +import seaborn as sns +import warnings +from ctypes import cdll, POINTER, c_float, c_int32, c_char_p, create_string_buffer +from collections import deque +from dataclasses import dataclass +# ROSCO toolbox modules +from rosco import discon_lib_path as lib_name from rosco.toolbox import controller as ROSCO_controller from rosco.toolbox import turbine as ROSCO_turbine +from rosco.toolbox import control_interface as ROSCO_ci +from rosco.toolbox import sim as ROSCO_sim +from rosco.toolbox.utilities import write_rotor_performance, write_DISCON from rosco.toolbox.inputs.validation import load_rosco_yaml def load_from_mitrotor( turbine, bem, refine_cp_surface=False, - TurbineName = "IEA15MW", GenEff = 95.756, generator_inertia = 1836784, + TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', + GenEff = 95.756, generator_inertia = 1836784, + yaw = 0.0 ): ''' Loads rotor performance information by running MITRotor aerodynamic analysis. @@ -26,7 +41,7 @@ def load_from_mitrotor( Returns: turbine with new fields needed for ROSCO controller, including Ct, Cp, and Cq surfaces ''' turbine.TurbineName = TurbineName - turbine.rotor_performance_filename = 'Cp_Ct_Cq.txt' + turbine.rotor_performance_filename = rotor_performance_filename (tower_height, gearbox_efficiency, gearbox_ratio, air_density) = bem.rotor.rosco_values turbine.TowerHt = tower_height @@ -37,7 +52,7 @@ def load_from_mitrotor( turbine.GenEff = GenEff turbine.generator_inertia = generator_inertia - turbine.yaw = 0.0 + turbine.yaw = yaw turbine.rotor_radius = bem.rotor.R turbine.J = turbine.rotor_inertia + turbine.generator_inertia * turbine.Ng**2 turbine.rated_torque = turbine.rated_power/(turbine.GenEff/100*turbine.rated_rotor_speed*turbine.Ng) @@ -58,8 +73,8 @@ def load_from_mitrotor( mit_sols = bem( pitch_rad_flat, tsr_flat, - yaw=np.zeros_like(tsr_flat), - tilt=np.zeros_like(tsr_flat), + yaw=np.ones_like(tsr_flat) * turbine.yaw, + tilt=np.ones_like(tsr_flat) * np.deg2rad(5.0), ) print('MITRotor aerodynamic analysis run successfully.') @@ -87,7 +102,8 @@ def load_from_mitrotor( def get_rosco_control_interps( rosco_yaml, bem, - TurbineName = "IEA15MW", GenEff = 95.756, generator_inertia = 1836784, + TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', SimName = "Sim1", + GenEff = 95.756, generator_inertia = 1836784, ): """ Creates pitch and tsr 1D interpolators using ROSCO controller tuning. @@ -109,22 +125,157 @@ def get_rosco_control_interps( turbine_params = inps['turbine_params'] controller_params = inps['controller_params'] + if controller_params["WE_Mode"] != 0: + warnings.warn( + "Using wind speed estimators in this simple simulation is known to cause problems. We suggest using WE_Mode = 0.", + UserWarning, + ) + # make turbine turbine = ROSCO_turbine.Turbine(turbine_params) turbine = load_from_mitrotor( turbine, bem, - TurbineName = TurbineName, generator_inertia = generator_inertia, GenEff = GenEff, + TurbineName = TurbineName, rotor_performance_filename = rotor_performance_filename, + generator_inertia = generator_inertia, GenEff = GenEff, + yaw = 0.0, ) + cp_filename = turbine.rotor_performance_filename + write_rotor_performance(turbine, txt_filename=cp_filename) # make controller controller = ROSCO_controller.Controller(controller_params) controller.tune_controller(turbine) + # Write parameter input file + # param_filename = os.path.join(this_dir,'DISCON.IN') + param_filename = 'DISCON.IN' + write_DISCON( + turbine,controller, + param_file=param_filename, + txt_filename=cp_filename + ) + + R = turbine.rotor_radius + GBRatio = turbine.Ng + dt = 0.025 + # sec2steady = 5 * 60 # length of time to simulate (s) + # t_list = np.arange(0, sec2steady, dt) + # ws_list = np.ones_like(t_list) + init_pitch_list = np.rad2deg(np.maximum(controller.pitch_op, controller.ps_min_bld_pitch)) + init_tsr_list = controller.TSR_op + # ss_win = 20 + + yaw_grid = np.array([0]) + v_grid = controller.v.copy() + + pitch_tbl = np.zeros((len(v_grid), len(yaw_grid))) + tsr_tbl = np.zeros_like(pitch_tbl) + start = 0 + for (ii, v) in enumerate(v_grid[start:]): + i = start + ii + # ws_list.fill(v) + init_pitch = init_pitch_list[i] + init_tsr = init_tsr_list[i] + # init_rmp = (init_tsr * v / R) * 60 / (2 * np.pi) + for (j, yaw) in enumerate(yaw_grid): + # Load controller library + # controller_int = ROSCO_ci.ControllerInterface( + # lib_name, param_filename = param_filename, sim_name=f"{SimName}_{i}_{j}", + # ) + + omega0 = init_tsr * v / R # rad/s + gen0 = omega0 * GBRatio + controller_int = WarmStartControllerInterface( + lib_name, + param_filename=param_filename, + sim_name=f"{SimName}_{i}_{j}", + DT=dt, + init_ws=v, + init_rot_speed=omega0, + init_gen_speed=gen0, + init_pitch_deg=init_pitch, # init_pitch is in deg + init_torque=0.0, + init_nac_imu=np.deg2rad(yaw), + ) + + # Load the simulator + sim = ROSCO_sim.Sim(turbine, controller_int) + + sim_ws_mitrotor( + sim, bem, v, dt, init_tsr, init_pitch, yaw_init = yaw, + ) + + pitch_tbl[i, j] = sim.bld_pitch + tsr_tbl[i, j] = sim.tsr + + # Run the simulation + # sim.sim_ws_series( + # t_list, ws_list, + # init_pitch = init_pitch, rotor_rpm_init = init_rmp, yaw_init = np.deg2rad(yaw), + # make_plots=False, + # ) + + # nss = int(ss_win/dt) # number of steady-state steps + # pitch_ss = np.mean(sim.bld_pitch[-nss:]) + # omega_ss = np.mean(sim.rot_speed[-nss:]) + # tsr_ss = omega_ss * R / v + + # pitch_tbl[i, j] = pitch_ss + # tsr_tbl[i, j] = tsr_ss + + # plot_pitch_tsr_vs_wind(v_grid, yaw_grid, pitch_tbl, tsr_tbl, pitch_in_rad=True) + # get interpolators - pitch_interp = rosco_pitch_interp(controller) - tsr_interp = rosco_tsr_interp(controller) + # pitch_interp = rosco_pitch_interp(controller) + # tsr_interp = rosco_tsr_interp(controller) + + wind_tbl = controller.v + pitch_interp = interp1d(wind_tbl, pitch_tbl[:, 0], kind="linear", fill_value="extrapolate", bounds_error=False) + tsr_interp = interp1d(wind_tbl, tsr_tbl[:, 0], kind="linear", fill_value="extrapolate", bounds_error=False) + + return pitch_interp, tsr_interp, turbine.rated_rotor_speed + +def plot_pitch_tsr_vs_wind(wind_speeds, yaw_vals, pitch_tbl, tsr_tbl, pitch_in_rad=True): + sns.set_theme(style="whitegrid") + + n_yaw = len(yaw_vals) + colors = sns.color_palette("viridis", n_colors=n_yaw) + + fig, axes = plt.subplots(2, 1, figsize=(8, 8), sharex=True) + + # If stored in radians, convert to degrees for plotting + pitch_plot = np.rad2deg(pitch_tbl) if pitch_in_rad else pitch_tbl + + # Plot one line per yaw + for j, yaw in enumerate(yaw_vals): + sns.lineplot( + x=wind_speeds, y=pitch_plot[:, j], + ax=axes[0], color=colors[j], linewidth=2 + ) + sns.lineplot( + x=wind_speeds, y=tsr_tbl[:, j], + ax=axes[1], color=colors[j], linewidth=2 + ) + + axes[0].set_ylabel("Pitch (deg)" if pitch_in_rad else "Pitch") + axes[0].set_title("Steady-State Pitch vs Wind Speed") + + axes[1].set_xlabel("Wind Speed (m/s)") + axes[1].set_ylabel("TSR (-)") + axes[1].set_title("Steady-State TSR vs Wind Speed") - return pitch_interp, tsr_interp + # One shared legend + legend_handles = [ + Line2D([0], [0], color=colors[j], lw=2, label=f"{yaw:g}°") + for j, yaw in enumerate(yaw_vals) + ] + fig.legend(handles=legend_handles, title="Yaw", loc="center right") + plt.tight_layout(rect=[0, 0, 0.88, 1]) # leave room for legend + plt.savefig("pitch_tsr_plots.png") + + +# Example call: +# plot_pitch_tsr_vs_wind(U_grid, yaw_grid, pitch_tbl, tsr_tbl, pitch_in_rad=True) def rosco_pitch_interp(controller): """ @@ -147,3 +298,424 @@ def rosco_tsr_interp(controller): wind_table = controller.v tsr_table = controller.TSR_op return interp1d(wind_table, tsr_table, kind="linear", fill_value="extrapolate", bounds_error=False) + + +deg2rad = np.deg2rad(1) +rad2deg = np.rad2deg(1) +rpm2RadSec = 2.0*(np.pi)/60.0 + + +def sim_ws_mitrotor( + sim, bem, ws, dt, init_tsr, init_pitch, + wd=0.0, yaw_init=0.0, + max_iter = 10000, tol = 1e-2, +): + # Store turbine data for convenience + R = sim.turbine.rotor_radius + rho = sim.turbine.rho + GBRatio = sim.turbine.Ng + + # Declare output arrays + bld_pitch = init_pitch * deg2rad + tsr = init_tsr + rot_speed = (tsr * ws / R) #rad / s + gen_speed = rot_speed * GBRatio + aero_torque = 1000.0 + gen_torque = 1.0 + gen_power = 0.0 + nac_yaw = yaw_init + nac_yawerr = 0.0 + nac_yawrate = 0.0 + + # Loop through time + n_iter = 0 + t = 0.0 + while n_iter < max_iter: + t += dt + tsr = rot_speed * R / ws + gamma = wd - nac_yaw + sol = bem(bld_pitch, tsr, yaw = gamma) + cp = sol.Cp() + + # Update the turbine state + # -- 1DOF model: rotor speed and generator speed (scaled by Ng) + aero_torque = 0.5 * rho * (np.pi * R**3) * (cp/tsr) * ws**2 + rot_speed = rot_speed + (dt/sim.turbine.J)*(aero_torque - sim.turbine.Ng * gen_torque / (sim.turbine.GBoxEff/100)) + gen_speed = rot_speed * sim.turbine.Ng + + # populate turbine state dictionary + turbine_state = {} + turbine_state['iStatus'] = 1 + turbine_state['t'] = t + turbine_state['dt'] = dt + turbine_state['ws'] = ws + turbine_state['bld_pitch'] = bld_pitch + turbine_state['gen_torque'] = gen_torque + turbine_state['gen_speed'] = gen_speed + turbine_state['gen_eff'] = sim.turbine.GenEff/100 + turbine_state['rot_speed'] = rot_speed + turbine_state['Yaw_fromNorth'] = nac_yaw + turbine_state['Y_MeasErr'] = gamma + + # Define outputs + gen_torque, bld_pitch, nac_yawrate = sim.controller_int.call_controller(turbine_state) + + # Calculate the power + gen_power_old = gen_power + gen_power = gen_speed * gen_torque * sim.turbine.GenEff / 100 + # Calculate the nacelle position + nac_yaw += nac_yawrate * dt + + if (gen_power_old - gen_power < tol) and (n_iter > 60 / dt): + print(f"Converged after {n_iter} with Power: {gen_power} kW") + break + n_iter += 1 + + sim.controller_int.kill_discon() + + # Save these values + sim.bld_pitch = bld_pitch + sim.tsr = rot_speed * R / ws + # self.rot_speed = rot_speed + # self.gen_speed = gen_speed + # self.aero_torque = aero_torque + # self.gen_torque = gen_torque + # self.gen_power = gen_power + # self.ws = ws + # self.wd = wd + # self.nac_yaw = nac_yaw + + +# from rosco.toolbox.control_interface import ControllerInterface +# # ------------------------------------------------------------- +# # Try generating 2D lookup table with ROSCO!! +# # ------------------------------------------------------------- + +# def _parse_rosco_outputs(out): +# """ +# Handle slight API differences in ROSCO toolbox versions. +# Expected: pitch command (rad, collective) and generator torque command (N-m). +# """ +# # dict-like +# if isinstance(out, dict): +# if "bld_pitch_cmd" in out: +# beta_cmd = np.atleast_1d(out["bld_pitch_cmd"])[0] +# elif "pitch_cmd" in out: +# beta_cmd = np.atleast_1d(out["pitch_cmd"])[0] +# else: +# raise KeyError("Could not find pitch command in ROSCO output dict.") + +# if "gen_torque_cmd" in out: +# Tg_cmd = out["gen_torque_cmd"] +# elif "torque_cmd" in out: +# Tg_cmd = out["torque_cmd"] +# else: +# raise KeyError("Could not find torque command in ROSCO output dict.") +# return float(beta_cmd), float(Tg_cmd) + +# # tuple/list-like fallback +# if isinstance(out, (tuple, list)) and len(out) >= 2: +# beta_cmd = np.atleast_1d(out[0])[0] +# Tg_cmd = out[1] +# return float(beta_cmd), float(Tg_cmd) + +# raise TypeError("Unknown ROSCO controller return type.") + + +# def _call_rosco(ci, t, dt, beta, omega, Tg, Ng, U_meas): +# """ +# Version-tolerant ROSCO call wrapper. +# You may need to tweak keyword names once for your installed ROSCO version. +# """ +# # Try common signature 1 +# try: +# out = ci.call_controller( +# t=t, +# dt=dt, +# bld_pitch=np.array([beta, beta, beta]), +# gen_speed=omega * Ng, +# gen_torque=Tg, +# rot_speed=omega, +# wind_speed=U_meas, +# ) +# return _parse_rosco_outputs(out) +# except TypeError: +# pass + +# # Try common signature 2 +# out = ci.call_controller( +# t, dt, +# np.array([beta, beta, beta]), +# omega * Ng, +# Tg, +# omega, +# U_meas, +# ) +# return _parse_rosco_outputs(out) + + +# def generate_rosco_2d_tables_full_rosco( +# rosco_yaml, +# bem, +# wind_table, +# yaw_table, +# discon_lib_path, # compiled ROSCO shared lib (e.g., libdiscon.so / discon.dll) +# discon_in_path, # DISCON.IN from ROSCO tuning +# TurbineName="IEA15MW", +# GenEff=95.756, +# generator_inertia=1836784, +# dt=0.05, +# t_max=220.0, +# tilt_deg=5.0, +# min_ws=0.25, +# omega_eps=0.2, +# tau_pitch=0.35, +# tau_torque=0.20, +# pitch_rate_max=np.deg2rad(8.0), +# torque_rate_max=3e6, +# t_min_check=20.0, +# conv_window=4.0, +# avg_window=5.0, +# tol_omega=2e-3, +# tol_pitch=np.deg2rad(0.03), +# tol_torque=2e4, +# save_npz=None, +# ): +# """ +# Fully ROSCO-controlled trim-map generation (no hand-coded region logic). +# """ +# # Load turbine properties via your existing pipeline +# inps = load_rosco_yaml(rosco_yaml) +# turbine = ROSCO_turbine.Turbine(inps["turbine_params"]) +# turbine = load_from_mitrotor( +# turbine, bem, +# TurbineName=TurbineName, +# GenEff=GenEff, +# generator_inertia=generator_inertia, +# yaw=0.0, +# ) + +# # For initialization only (NOT control logic) +# pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( +# rosco_yaml, bem, +# TurbineName=TurbineName, GenEff=GenEff, generator_inertia=generator_inertia +# ) + +# # ROSCO DLL interface +# ci = ControllerInterface(discon_lib_path, discon_in_path) + +# R = float(bem.rotor.R) +# A = np.pi * R**2 +# rho = float(turbine.rho) +# Ng = float(turbine.Ng) +# J = float(turbine.J) + +# gbox_eff = float(turbine.GBoxEff) +# if gbox_eff > 1.5: # percent -> fraction +# gbox_eff /= 100.0 +# gbox_eff = np.clip(gbox_eff, 1e-3, 1.0) + +# wind_table = np.asarray(wind_table, dtype=float) +# yaw_table = np.asarray(yaw_table, dtype=float) + +# nW, nY = len(wind_table), len(yaw_table) +# tabs = { +# "wind_table": wind_table, +# "yaw_table": yaw_table, +# "pitch": np.zeros((nW, nY)), +# "omega": np.zeros((nW, nY)), +# "tsr_bem": np.zeros((nW, nY)), +# "tsr_normal": np.zeros((nW, nY)), +# "Cp": np.zeros((nW, nY)), +# "Ct": np.zeros((nW, nY)), +# "a": np.zeros((nW, nY)), +# "power": np.zeros((nW, nY)), +# "converged": np.zeros((nW, nY), dtype=bool), +# } + +# n_steps = int(t_max / dt) +# n_conv = max(3, int(conv_window / dt)) +# n_avg = max(3, int(avg_window / dt)) + +# for j, yaw_deg in enumerate(yaw_table): +# yaw = np.deg2rad(yaw_deg) +# tilt = np.deg2rad(tilt_deg) + +# # warm start along wind +# state = None + +# for i, U_in in enumerate(wind_table): +# U = max(float(U_in), min_ws) +# U_n = max(U * np.cos(yaw) * np.cos(tilt), min_ws) + +# # init state +# if state is None: +# lam0 = max(float(tsr_interp(U_n)), 0.1) +# omega = max(lam0 * U_n / R, omega_eps) +# beta = float(pitch_interp(U_n)) +# Tg = float(turbine.rated_torque * (omega / max(rated_rotor_speed, 1e-3))**2) +# else: +# omega, beta, Tg = state["omega"], state["beta"], state["Tg"] + +# omega_hist, beta_hist, Tg_hist = [], [], [] +# cp_hist, ct_hist, a_hist = [], [], [] +# converged = False + +# for k in range(n_steps): +# t = k * dt +# omega = max(omega, omega_eps) + +# # --- ROSCO gives commands (fully controller-managed) --- +# beta_cmd, Tg_cmd = _call_rosco( +# ci=ci, t=t, dt=dt, +# beta=beta, omega=omega, Tg=Tg, Ng=Ng, +# U_meas=U_n, # rotor-normal measured wind +# ) + +# # actuator dynamics / limits (plant-side, not control policy) +# dbeta = np.clip((beta_cmd - beta) / tau_pitch, -pitch_rate_max, pitch_rate_max) +# dTg = np.clip((Tg_cmd - Tg) / tau_torque, -torque_rate_max, torque_rate_max) +# beta += dbeta * dt +# Tg += dTg * dt + +# # MITRotor aero +# tsr_bem = omega * R / U +# sol = bem( +# np.array([beta]), +# np.array([tsr_bem]), +# yaw=np.array([yaw]), +# tilt=np.array([tilt]), +# ) +# Cp = float(sol.Cp()[0]) +# Ct = float(sol.Ct()[0]) +# a = float(sol.a()[0]) + +# P = 0.5 * rho * A * Cp * U**3 +# Qaero = P / max(omega, omega_eps) +# Qgen_rotor = Tg * Ng / gbox_eff +# domega = (Qaero - Qgen_rotor) / J +# omega = max(omega + domega * dt, omega_eps) + +# omega_hist.append(omega) +# beta_hist.append(beta) +# Tg_hist.append(Tg) +# cp_hist.append(Cp) +# ct_hist.append(Ct) +# a_hist.append(a) + +# if t >= t_min_check and len(omega_hist) >= n_conv: +# if (np.ptp(omega_hist[-n_conv:]) < tol_omega and +# np.ptp(beta_hist[-n_conv:]) < tol_pitch and +# np.ptp(Tg_hist[-n_conv:]) < tol_torque): +# converged = True +# break + +# # steady averages +# omega_ss = float(np.mean(omega_hist[-n_avg:])) +# beta_ss = float(np.mean(beta_hist[-n_avg:])) +# Cp_ss = float(np.mean(cp_hist[-n_avg:])) +# Ct_ss = float(np.mean(ct_hist[-n_avg:])) +# a_ss = float(np.mean(a_hist[-n_avg:])) + +# tabs["pitch"][i, j] = beta_ss +# tabs["omega"][i, j] = omega_ss +# tabs["tsr_bem"][i, j] = omega_ss * R / U +# tabs["tsr_normal"][i, j] = omega_ss * R / U_n +# tabs["Cp"][i, j] = Cp_ss +# tabs["Ct"][i, j] = Ct_ss +# tabs["a"][i, j] = a_ss +# tabs["power"][i, j] = 0.5 * rho * A * Cp_ss * U**3 +# tabs["converged"][i, j] = converged + +# state = {"omega": omega, "beta": beta, "Tg": Tg} + +# if not converged: +# print(f"[warn] not converged at U={U:.2f}, yaw={yaw_deg:.2f}") + +# if save_npz is not None: +# np.savez(save_npz, **tabs) + +# return tabs + +class WarmStartControllerInterface(ROSCO_ci.ControllerInterface): + def __init__( + self, + lib_name, + param_filename="DISCON.IN", + init_ws=10.0, # m/s + init_rot_speed=1.0, # rad/s (LSS) + init_gen_speed=1.0, # rad/s (HSS) + init_pitch_deg=0.0, # deg + init_torque=0.0, # Nm + init_nac_imu=0.0, # rad + **kwargs + ): + self.init_ws = float(init_ws) + self.init_rot_speed = float(init_rot_speed) + self.init_gen_speed = float(init_gen_speed) + self.init_torque = float(init_torque) + self.init_nac_imu = float(init_nac_imu) + + # parent uses self.pitch for initial blade pitch + super().__init__( + lib_name, + param_filename=param_filename, + pitch=init_pitch_deg, + **kwargs + ) + + def init_discon(self): + self.torque = self.init_torque + + # Load library + allocate swap + self.discon = cdll.LoadLibrary(self.lib_name) + self.avrSWAP = np.zeros(self.avr_size) + + # Required channels + self.avrSWAP[2] = self.DT + self.avrSWAP[60] = self.num_blade + + # --- warm-start initial states (replaces hard-coded values) --- + self.avrSWAP[19] = self.init_gen_speed # gen speed [rad/s] + self.avrSWAP[20] = self.init_rot_speed # rot speed [rad/s] + self.avrSWAP[82] = self.init_nac_imu # nac IMU + self.avrSWAP[26] = self.init_ws # wind speed [m/s] + self.avrSWAP[22] = self.init_torque # gen torque [Nm] + + # Initial blade pitch (all blades) + pitch_rad = self.pitch * np.deg2rad(1.0) + self.avrSWAP[3] = pitch_rad + self.avrSWAP[32] = pitch_rad + self.avrSWAP[33] = pitch_rad + + self.avrSWAP[27] = 1 # IPC flag + + # First-call init + self.avrSWAP[0] = 0 + + self.aviFAIL = c_int32() + self.accINFILE = self.param_name.encode("utf-8") + self.avcOUTNAME = self.sim_name.encode("utf-8") + self.avcMSG = create_string_buffer(1000) + + self.discon.DISCON.argtypes = [ + POINTER(c_float), + POINTER(c_int32), + c_char_p, + c_char_p, + c_char_p, + ] + + self.avrSWAP[48] = self.char_buffer + self.avrSWAP[49] = len(self.param_name) + self.avrSWAP[50] = len(self.avcOUTNAME) + self.avrSWAP[51] = self.char_buffer + + self.call_discon() # iStatus=0 init call + self.avrSWAP[0] = 1 # subsequent calls are normal + + if self.aviFAIL.value < 0: + raise ValueError("ROSCO dynamic library has returned an error") + + + diff --git a/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml index 8046f29..85a5d3a 100644 --- a/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml +++ b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml @@ -35,7 +35,7 @@ controller_params: PC_ControlMode: 1 # Blade pitch control mode {0: No pitch, fix to fine pitch, 1: active PI blade pitch control} Y_ControlMode: 0 # Yaw control mode {0: no yaw control, 1: yaw rate control, 2: yaw-by-IPC} SS_Mode: 1 # Setpoint Smoother mode {0: no setpoint smoothing, 1: introduce setpoint smoothing} - WE_Mode: 2 # Wind speed estimator mode {0: One-second low pass filtered hub height wind speed, 1: Immersion and Invariance Estimator (Ortega et al.)} + WE_Mode: 0 # Wind speed estimator mode {0: One-second low pass filtered hub height wind speed, 1: Immersion and Invariance Estimator (Ortega et al.)} PS_Mode: 3 # Pitch saturation mode {0: no pitch saturation, 1: peak shaving, 2: Cp-maximizing pitch saturation, 3: peak shaving and Cp-maximizing pitch saturation} SD_Mode: 0 # Shutdown mode {0: no shutdown procedure, 1: pitch to max pitch at shutdown} Fl_Mode: 2 # Floating specific feedback mode {0: no nacelle velocity feedback, 1: nacelle velocity feedback} diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 414ff08..d6b1cc4 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -38,8 +38,8 @@ def change_control_param(param_key, param_value, template_yaml, bem): with open(temp_yaml, "w") as f: yaml.dump(data, f) - pitch_interp, tsr_interp = get_rosco_control_interps(temp_yaml, bem) - return pitch_interp, tsr_interp + pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps(temp_yaml, bem) + return pitch_interp, tsr_interp, rated_rotor_speed def get_turbine_power_coefficent(bem, fmodel, wind_speeds): rotor_area = np.pi * bem.rotor.R**2 @@ -73,7 +73,7 @@ def main(): cache_file = cache_dir / "lut.csv" lut_model = UnifiedMomentumLUT( cache_fn=cache_file, - regenerate=True, + regenerate=False, LUT_Cts=np.linspace(-0.5,1.5,40), LUT_yaws=np.linspace(0.0,25.1,25), ) @@ -81,23 +81,23 @@ def main(): # # Load IEA15MW ROSCO parameters to make controllers rosco_yaml_PS_Mode_3 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" - rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp = get_rosco_control_interps(rosco_yaml_PS_Mode_3, bem) - rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp = change_control_param("PS_Mode", 0, rosco_yaml_PS_Mode_3, bem) + rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp, rosco_PS_Mode_3_rated_rotorspeed = get_rosco_control_interps(rosco_yaml_PS_Mode_3, bem) + # rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param("PS_Mode", 0, rosco_yaml_PS_Mode_3, bem) # Plot IEA15MW control from ROSCO paper, ROSOC control with PS_Mode = 3, and ROSOC control with PS_Mode = 0 pitch_abbas = abbas_pitch_interp(wind_speeds) - pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) + # pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) pitch_ps3 = np.rad2deg(rosco_PS_Mode_3_pitch_interp(wind_speeds)) tsr_abbas = abbas_tsr_interp(wind_speeds) - tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) + # tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) tsr_ps3 = rosco_PS_Mode_3_tsr_interp(wind_speeds) # Create figure fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) fig.suptitle(fr"Setpoint Trajectories") # Plot pitch - ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) + # ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") @@ -108,7 +108,7 @@ def main(): # ax[0].legend() # Plot TSR - ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) + # ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") @@ -132,18 +132,20 @@ def main(): tsr_interp = abbas_tsr_interp, ) - floris_PS_Mode_0_turbine = MITRotorTurbine( - bem_model = bem, - pitch_interp = rosco_PS_Mode_0_pitch_interp, - pitch_rad = True, - tsr_interp = rosco_PS_Mode_0_tsr_interp, - ) + # floris_PS_Mode_0_turbine = MITRotorTurbine( + # bem_model = bem, + # pitch_interp = rosco_PS_Mode_0_pitch_interp, + # pitch_rad = True, + # tsr_interp = rosco_PS_Mode_0_tsr_interp, + # rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, + # ) floris_PS_Mode_3_turbine = MITRotorTurbine( bem_model = bem, pitch_interp = rosco_PS_Mode_3_pitch_interp, pitch_rad = True, tsr_interp = rosco_PS_Mode_3_tsr_interp, + rated_rotor_speed = rosco_PS_Mode_3_rated_rotorspeed, ) yaw = 0.0 # degrees yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] @@ -162,12 +164,12 @@ def main(): Cp_abbas, P_abbas = get_turbine_power_coefficent(bem, fmodel_abbas, wind_speeds) - fmodel_PS_Mode_0 = FlorisModel("defaults") - fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) - fmodel_PS_Mode_0.run() - Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() - Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_0, wind_speeds) + # fmodel_PS_Mode_0 = FlorisModel("defaults") + # fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + # fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) + # fmodel_PS_Mode_0.run() + # Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() + # Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_0, wind_speeds) fmodel_PS_Mode_3 = FlorisModel("defaults") fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) @@ -177,7 +179,7 @@ def main(): Cp_PS_Mode_3, P_PS_Mode_3 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) - fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (15,4), constrained_layout=True) + fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (16,4), constrained_layout=True) fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = 0 for Different Control Strategies") ax1.plot( wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", @@ -187,10 +189,10 @@ def main(): wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", lw=3, linestyle = "solid", zorder = 1, ) - ax1.plot( - wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", - lw=3, linestyle = "dashed", zorder = 1, - ) + # ax1.plot( + # wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", + # lw=3, linestyle = "dashed", zorder = 1, + # ) ax1.plot(wind_speeds, Ct_PS_Mode_3, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -208,10 +210,10 @@ def main(): wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "solid", zorder = 1, ) - ax2.plot( - wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - lw=3, linestyle = "dashed", zorder = 1, - ) + # ax2.plot( + # wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + # lw=3, linestyle = "dashed", zorder = 1, + # ) ax2.plot(wind_speeds, Cp_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -229,10 +231,10 @@ def main(): wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "solid", zorder = 1, ) - ax3.plot( - wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - lw=3, linestyle = "dashed", zorder = 1, - ) + # ax3.plot( + # wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + # lw=3, linestyle = "dashed", zorder = 1, + # ) ax3.plot(wind_speeds, P_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -240,49 +242,49 @@ def main(): ax3.set_ylabel("$Power [MW]$") ax3.set_title("$Power$") ax3.grid(True) - ax3.legend() + ax3.legend(loc = 'lower left') plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) - # plot the difference in CT/CP curves for different yaw values - yaw_list = [0.0, 10.0, 20.0] # degrees - fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) - fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: PS_Mode = 3") - for (i, yaw) in enumerate(yaw_list): - yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] - fmodel_PS_Mode_3 = FlorisModel("defaults") - fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) - fmodel_PS_Mode_3.run() - ct = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() - cp, p = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) - - ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", - lw=3, linestyle = "solid", zorder = 1, - ) - ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", - lw=3, linestyle = "solid", zorder = 1, - ) - ax3.plot(wind_speeds, p, label=fr"Yaw = ${yaw}^\circ$", - lw=3, linestyle = "solid", zorder = 1, - ) - - ax1.set_xlabel("Wind Speed [m/s]") - ax1.set_ylabel("$C_T [-]$") - ax1.set_title("$C_T$") - ax1.grid(True) - - ax2.set_xlabel("Wind Speed [m/s]") - ax2.set_ylabel("$C_P [-]$") - ax2.set_title("$C_P$") - ax2.grid(True) - - ax3.set_xlabel("Wind Speed [m/s]") - ax3.set_ylabel("$Power [MW]$") - ax3.set_title("$Power$") - ax3.grid(True) - ax3.legend() - plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) + # # plot the difference in CT/CP curves for different yaw values + # yaw_list = [0.0, 10.0, 20.0] # degrees + # fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) + # fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: PS_Mode = 3") + # for (i, yaw) in enumerate(yaw_list): + # yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] + # fmodel_PS_Mode_3 = FlorisModel("defaults") + # fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + # fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) + # fmodel_PS_Mode_3.run() + # ct = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() + # cp, p = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) + + # ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", + # lw=3, linestyle = "solid", zorder = 1, + # ) + # ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", + # lw=3, linestyle = "solid", zorder = 1, + # ) + # ax3.plot(wind_speeds, p, label=fr"Yaw = ${yaw}^\circ$", + # lw=3, linestyle = "solid", zorder = 1, + # ) + + # ax1.set_xlabel("Wind Speed [m/s]") + # ax1.set_ylabel("$C_T [-]$") + # ax1.set_title("$C_T$") + # ax1.grid(True) + + # ax2.set_xlabel("Wind Speed [m/s]") + # ax2.set_ylabel("$C_P [-]$") + # ax2.set_title("$C_P$") + # ax2.grid(True) + + # ax3.set_xlabel("Wind Speed [m/s]") + # ax3.set_ylabel("$Power [MW]$") + # ax3.set_title("$Power$") + # ax3.grid(True) + # ax3.legend() + # plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) # VALUES FROM THE LAST YAW EXAMPLE # yaw_angles = [0.0, 10.0, 20.0] diff --git a/poetry.lock b/poetry.lock index acd7f3c..9e62a5e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4466,6 +4466,28 @@ dev = ["click (<8.3.0)", "cython-lint (>=0.12.2)", "mypy (==1.10.0)", "pycodesty doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)", "tabulate"] test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "seaborn" +version = "0.13.2" +description = "Statistical data visualization" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987"}, + {file = "seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7"}, +] + +[package.dependencies] +matplotlib = ">=3.4,<3.6.1 || >3.6.1" +numpy = ">=1.20,<1.24.0 || >1.24.0" +pandas = ">=1.2" + +[package.extras] +dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] +docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx (<6.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] +stats = ["scipy (>=1.7)", "statsmodels (>=0.12)"] + [[package]] name = "send2trash" version = "2.1.0" @@ -5196,4 +5218,4 @@ viz = ["cartopy (>=0.24)", "matplotlib (>=3.10)", "nc-time-axis", "seaborn"] [metadata] lock-version = "2.1" python-versions = ">3.10, <3.15" -content-hash = "61f7d0b43670dfa0ac04404950bbd30671629fa95a5f30ba89114c20c7608fb5" +content-hash = "06e1ae0fa2d7a9ffaef337f0c3f5bd81c913f6884ee640d925b8c206da6d7d4d" diff --git a/pyproject.toml b/pyproject.toml index 05c7269..d01e8b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ pyyaml = "^6.0.1" floris = {git = "https://github.com/misi9170/floris.git", branch = "feature/user-def-op-mod"} rosco = "^2.10.4" ruamel-yaml = "^0.19.1" +seaborn = "^0.13.2" [tool.poetry.group.dev.dependencies] black = { extras = ["jupyter"], version = "^23.9.1" } From ee1e2d5386e94a60e8170fd3b0466579b1d516ce Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 3 Jul 2026 12:59:04 -0400 Subject: [PATCH 26/50] Working 2D interpolator --- MITRotor/FlorisInterface/FlorisInterface.py | 55 +- MITRotor/FlorisInterface/ROSCOInterface.py | 935 ++++++++++---------- MITRotor/FlorisInterface/ROSCOUtilities.py | 0 examples/example_08_floris_rosco.py | 290 +++--- 4 files changed, 641 insertions(+), 639 deletions(-) create mode 100644 MITRotor/FlorisInterface/ROSCOUtilities.py diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index b45fa79..102575f 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -3,7 +3,7 @@ import polars as pl from attrs import define, field from typing import Optional -from scipy.interpolate import interp1d +from scipy.interpolate import interp1d, RegularGridInterpolator # FLORIS Imports from floris.type_dec import floris_float_type, NDArrayFloat from floris.core.turbine.operation_models import BaseOperationModel @@ -15,6 +15,8 @@ from MITRotor.Geometry import BEMGeometry from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM +from MITRotor.FlorisInterface.ROSCOInterface import query_controls +from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw # default rotor if none provided by user (IEA 15MW) def default_bem_factory(): @@ -66,12 +68,17 @@ class MITRotorTurbine(BaseOperationModel): """ # user can define a BEM model if they want a different rotor, momentum model, or geometry bem_model = field(init = True, factory = default_bem_factory, type = BEM) + gen_eff = field(init = True, default = 95.756, type=Optional[float]) # [%] + eff_ratio = field(init=True, default=None, type=Optional[float]) # allow override + # TODO: figure out the default factory for the tsr and pitch!! Use saved file... # create interp objects based on pitch and tsr csvs - pitch_interp = field(init = True, factory = default_pitch_interp, type = interp1d, repr = False) + # pitch_interp = field(init = True, factory = default_pitch_interp, type = interp1d, repr = False) + pitch_interp = field(init = True, default = None, type = RegularGridInterpolator, repr = False) pitch_rad = field(init = True, default = True, type = bool) - tsr_interp = field(init = True, factory = default_tsr_interp, type = interp1d, repr = False) - rated_rotor_speed = field(init=True, default=None, type=Optional[float]) # rad/s + # tsr_interp = field(init = True, factory = default_tsr_interp, type = interp1d, repr = False) + tsr_interp = field(init = True, default = False, type = RegularGridInterpolator, repr = False) + rated_rotor_speed = field(init=True, default=None, type=Optional[float]) # [rad/s] # save most recent solution by unique floris arguments _last_key = field(init=False, default=None, type = bytes) @@ -79,6 +86,11 @@ class MITRotorTurbine(BaseOperationModel): _Ct = field(init=False, default=None, type = NDArrayFloat) _power = field(init=False, default=None, type = NDArrayFloat) + def __attrs_post_init__(self): + if self.eff_ratio is None: + gearbox_eff = self.bem_model.rotor.rosco_values[1] + self.eff_ratio = (self.gen_eff / 100.0) * (gearbox_eff / 100.0) + def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_angles: np.ndarray) -> tuple: # saves key to uniquely identify farm state -> avoids re-solving for calls to power, thrust, and induction for same state return velocities.tobytes(), yaw_angles.tobytes(), tilt_angles.tobytes() @@ -111,28 +123,27 @@ def _update_solution(self, method=average_method, cubature_weights=cubature_weights, ) - # self.farm.cosine_loss_exponent_yaw - pW = power_thrust_table["cosine_loss_exponent_yaw"] / 3.0 - rotor_normal_average_velocities = rotor_average_velocities * (cosd(yaw_angles) ** pW) - # rotor_normal_average_velocities = rotor_average_velocities * cosd(yaw_angles) * cosd(tilt_angles) # calculate rotor area rotor_area = np.pi * self.bem_model.rotor.R**2 # get setpoints yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) - pitch = self.pitch_interp(rotor_normal_average_velocities) + eff_yaw = calc_eff_yaw(yaw, tilt) + pitch = query_controls(self.pitch_interp, rotor_average_velocities, eff_yaw) + tsr = query_controls(self.tsr_interp, rotor_average_velocities, eff_yaw) + # pitch = self.pitch_interp(rotor_normal_average_velocities) if not self.pitch_rad: pitch = np.deg2rad(pitch) - if self.rated_rotor_speed is None: - tsr = self.tsr_interp(rotor_normal_average_velocities) - else: - R = self.bem_model.rotor.R - tsr_lookup = self.tsr_interp(rotor_normal_average_velocities) - omega_lookup = tsr_lookup * rotor_normal_average_velocities / R # rad/s implied by lookup - tsr_from_rated_speed = self.rated_rotor_speed * R / rotor_average_velocities # above-rated branch - tsr = np.where(omega_lookup <= self.rated_rotor_speed, tsr_lookup, tsr_from_rated_speed) - tsr = np.maximum(tsr, 0.0) + # if self.rated_rotor_speed is None: + # tsr = self.tsr_interp(rotor_normal_average_velocities) + # else: + # R = self.bem_model.rotor.R + # tsr_lookup = self.tsr_interp(rotor_normal_average_velocities) + # omega_lookup = tsr_lookup * rotor_normal_average_velocities / R # rad/s implied by lookup + # tsr_from_rated_speed = self.rated_rotor_speed * R / rotor_average_velocities # above-rated branch + # tsr = np.where(omega_lookup <= self.rated_rotor_speed, tsr_lookup, tsr_from_rated_speed) + # tsr = np.maximum(tsr, 0.0) for tindex in range(n_turbines): # solve BEM @@ -140,8 +151,12 @@ def _update_solution(self, # get induction and thrust coeff self._a[:, tindex] = bem_sol.a() self._Ct[:, tindex] = bem_sol.Ct() - # compute power - self._power[:, tindex] = 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_average_velocities[:, tindex])**3 + # compute power -> need generator efficiency + self._power[:, tindex] = ( + 0.5 * bem_sol.Cp() * air_density * rotor_area + * (rotor_average_velocities[:, tindex])**3 + * self.eff_ratio + ) return def power(self, **kwargs) -> NDArrayFloat: diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 45e1fd0..5ed046e 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -1,14 +1,12 @@ # Python modules import os -import numpy as np -from scipy.interpolate import interp1d -import matplotlib.pyplot as plt -from matplotlib.lines import Line2D -import seaborn as sns -import warnings -from ctypes import cdll, POINTER, c_float, c_int32, c_char_p, create_string_buffer from collections import deque +from ctypes import cdll, POINTER, c_float, c_int32, c_char_p, create_string_buffer from dataclasses import dataclass +import numpy as np +from pathlib import Path +from scipy.interpolate import interp1d, RegularGridInterpolator +import warnings # ROSCO toolbox modules from rosco import discon_lib_path as lib_name from rosco.toolbox import controller as ROSCO_controller @@ -18,6 +16,9 @@ from rosco.toolbox.utilities import write_rotor_performance, write_DISCON from rosco.toolbox.inputs.validation import load_rosco_yaml +# ----------------------------- +# Create Ct/Cp surfaces +# ----------------------------- def load_from_mitrotor( turbine, bem, refine_cp_surface=False, TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', @@ -40,6 +41,7 @@ def load_from_mitrotor( Returns: turbine with new fields needed for ROSCO controller, including Ct, Cp, and Cq surfaces ''' + # Set turbine parameters turbine.TurbineName = TurbineName turbine.rotor_performance_filename = rotor_performance_filename @@ -57,7 +59,7 @@ def load_from_mitrotor( turbine.J = turbine.rotor_inertia + turbine.generator_inertia * turbine.Ng**2 turbine.rated_torque = turbine.rated_power/(turbine.GenEff/100*turbine.rated_rotor_speed*turbine.Ng) - # Generate the look-up tables, mesh the grid and flatten the arrays for cc_rotor aerodynamic analysis + # Generate the look-up tables, mesh the grid and flatten the arrays for aerodynamic analysis TSR_initial = np.arange(0.5, 25., 0.5) pitch_initial = np.arange(0.0, 31., 1.0) pitch_initial_rad = np.deg2rad(pitch_initial) @@ -100,556 +102,418 @@ def load_from_mitrotor( turbine.Cq = ROSCO_turbine.RotorPerformance(turbine.Cq_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) return turbine +# ----------------------------- +# Generate control scheme +# ----------------------------- def get_rosco_control_interps( rosco_yaml, bem, TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', SimName = "Sim1", GenEff = 95.756, generator_inertia = 1836784, + regenerate = False, + save_control_file = None, + save_dir = ".", + dt = 0.05, + yaw_grid_deg = np.arange(0.0, 25.0, 1.0), # in degrees ): """ - Creates pitch and tsr 1D interpolators using ROSCO controller tuning. + Creates pitch and tsr 2D interpolators using ROSCO controller tuning. + + Creates turbine and controller. Controller is tuned on yaw = 0 Cp/Ct surfaces from MITRotor. + ROSCO simulation with controller and turbrine is then run for each (wind_speed, yaw) combination + till steady state. Steady-state set points are made into a 2D interpolator and optionally saved to + a CSV. Args: - rosco_yaml (string): yaml file that defineds turbine and control parameters; + rosco_yaml (string): yaml file (+path) that defineds turbine and control parameters; [see MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml for example] bem (MITRotor.BEM): MITRotor BEM object TurbineName (string): string turbine name; default to "IEA15MW" GenEff (float): generator efficiency (0-100); defaults to IEA15MW value 95.756 generator_inertia (float): generator_inertia; defaults to IEA15MW value 1836784 [kg m^2] + save_control_file (string): file name (+path) of saved look-up table value; if None (default) then not saved + regenerate (bool): if True, then regenerate control path, else use saved in save_control_file; if save_control_file is None, set to True + save_dir (string): path to save all files output when creating the interpolaters + dt (float): timestep for ROSCO simulation; default = 0.05 seconds Returns: pitch_interp (string): 1D pitch interpolator from wind speed tuned with ROSCO control paramters tsr_interp (string): 1D tsr interpolator from wind speed tuned with ROSCO control paramters + rated_rotor_speed (float): rated rotor speed value """ - # load ROSCO inputs + + # load ROSCO inputs and make basic turbine inps = load_rosco_yaml(rosco_yaml) turbine_params = inps['turbine_params'] - controller_params = inps['controller_params'] + turbine = ROSCO_turbine.Turbine(turbine_params) + # if control csv exists and do not want to regenerate, load old csv + if not regenerate and save_control_file is not None: + pitch_interp, tsr_interp = load_control_interps_from_csv(save_control_file) + return pitch_interp, tsr_interp, turbine.rated_rotor_speed + + # load and check control parameters + controller_params = inps['controller_params'] if controller_params["WE_Mode"] != 0: warnings.warn( "Using wind speed estimators in this simple simulation is known to cause problems. We suggest using WE_Mode = 0.", UserWarning, ) - # make turbine - turbine = ROSCO_turbine.Turbine(turbine_params) + # generate turbine Cp/Ct surfaces turbine = load_from_mitrotor( turbine, bem, TurbineName = TurbineName, rotor_performance_filename = rotor_performance_filename, generator_inertia = generator_inertia, GenEff = GenEff, yaw = 0.0, ) + # save turbine Cp/Ct surface cp_filename = turbine.rotor_performance_filename write_rotor_performance(turbine, txt_filename=cp_filename) - # make controller + # make and tune controller controller = ROSCO_controller.Controller(controller_params) controller.tune_controller(turbine) # Write parameter input file - # param_filename = os.path.join(this_dir,'DISCON.IN') - param_filename = 'DISCON.IN' + param_filename = os.path.join(save_dir,'DISCON.IN') write_DISCON( turbine,controller, param_file=param_filename, txt_filename=cp_filename ) - R = turbine.rotor_radius - GBRatio = turbine.Ng - dt = 0.025 - # sec2steady = 5 * 60 # length of time to simulate (s) - # t_list = np.arange(0, sec2steady, dt) - # ws_list = np.ones_like(t_list) + # load initial setpoints from tuned controller init_pitch_list = np.rad2deg(np.maximum(controller.pitch_op, controller.ps_min_bld_pitch)) init_tsr_list = controller.TSR_op - # ss_win = 20 - yaw_grid = np.array([0]) + # load/set values for interpolator axes v_grid = controller.v.copy() + yaw_grid_deg = np.asarray(yaw_grid_deg, dtype=float) + yaw_grid_rad = np.deg2rad(yaw_grid_deg) - pitch_tbl = np.zeros((len(v_grid), len(yaw_grid))) + pitch_tbl = np.zeros((len(v_grid), len(yaw_grid_rad))) tsr_tbl = np.zeros_like(pitch_tbl) - start = 0 - for (ii, v) in enumerate(v_grid[start:]): - i = start + ii - # ws_list.fill(v) + power_tbl = np.zeros_like(pitch_tbl) + + # needed constants + R = turbine.rotor_radius + GBRatio = turbine.Ng + + # loop through interpolator axes and find setpoints using ROSCO simulation + for (i, v) in enumerate(v_grid): + # initial guess setpoints based on tuned controller init_pitch = init_pitch_list[i] init_tsr = init_tsr_list[i] - # init_rmp = (init_tsr * v / R) * 60 / (2 * np.pi) - for (j, yaw) in enumerate(yaw_grid): - # Load controller library - # controller_int = ROSCO_ci.ControllerInterface( - # lib_name, param_filename = param_filename, sim_name=f"{SimName}_{i}_{j}", - # ) - - omega0 = init_tsr * v / R # rad/s - gen0 = omega0 * GBRatio + init_omega = init_tsr * v / R + init_gen = init_omega * GBRatio + # loop through yaw + for (j, yaw_rad) in enumerate(yaw_grid_rad): + # create controller interface controller_int = WarmStartControllerInterface( lib_name, param_filename=param_filename, sim_name=f"{SimName}_{i}_{j}", DT=dt, init_ws=v, - init_rot_speed=omega0, - init_gen_speed=gen0, + init_rot_speed=init_omega, + init_gen_speed=init_gen, init_pitch_deg=init_pitch, # init_pitch is in deg init_torque=0.0, - init_nac_imu=np.deg2rad(yaw), + init_nac_imu=yaw_rad, # init_nac_imu is rad ) - # Load the simulator + # create the ROSCO simulation sim = ROSCO_sim.Sim(turbine, controller_int) - + # run the simulation to steady state sim_ws_mitrotor( - sim, bem, v, dt, init_tsr, init_pitch, yaw_init = yaw, + sim=sim, bem=bem, ws=v, dt=dt, + init_tsr=init_tsr, + init_pitch=init_pitch, # deg + yaw_init=yaw_rad, # rad + wd=0.0, ) - + # save setpoints in 2D tables pitch_tbl[i, j] = sim.bld_pitch - tsr_tbl[i, j] = sim.tsr - - # Run the simulation - # sim.sim_ws_series( - # t_list, ws_list, - # init_pitch = init_pitch, rotor_rpm_init = init_rmp, yaw_init = np.deg2rad(yaw), - # make_plots=False, - # ) - - # nss = int(ss_win/dt) # number of steady-state steps - # pitch_ss = np.mean(sim.bld_pitch[-nss:]) - # omega_ss = np.mean(sim.rot_speed[-nss:]) - # tsr_ss = omega_ss * R / v - - # pitch_tbl[i, j] = pitch_ss - # tsr_tbl[i, j] = tsr_ss - - # plot_pitch_tsr_vs_wind(v_grid, yaw_grid, pitch_tbl, tsr_tbl, pitch_in_rad=True) - - # get interpolators - # pitch_interp = rosco_pitch_interp(controller) - # tsr_interp = rosco_tsr_interp(controller) - - wind_tbl = controller.v - pitch_interp = interp1d(wind_tbl, pitch_tbl[:, 0], kind="linear", fill_value="extrapolate", bounds_error=False) - tsr_interp = interp1d(wind_tbl, tsr_tbl[:, 0], kind="linear", fill_value="extrapolate", bounds_error=False) + tsr_tbl[i, j] = sim.tsr + power_tbl[i, j] = sim.gen_power + + # save CSV of (optional) + if save_control_file is not None: + save_control_file = Path(save_control_file) + save_control_file.parent.mkdir(parents=True, exist_ok=True) + + vv, yy = np.meshgrid(v_grid, yaw_grid_rad, indexing="ij") + data = np.column_stack([ + vv.ravel(), # wind_speed_mps + yy.ravel(), # yaw_rad + pitch_tbl.ravel(), # pitch_rad + tsr_tbl.ravel(), # tsr + power_tbl.ravel(), # generated power + ]) + + header = "wind_speed_mps,yaw_rad,pitch_rad,tsr,gen_power" + np.savetxt(save_control_file, data, delimiter=",", header=header, comments="") + + # Direct 2D interpolators, no custom wrapper + pitch_interp = RegularGridInterpolator( + (v_grid, yaw_grid_rad), pitch_tbl, + method="linear", bounds_error=False, fill_value=None + ) + tsr_interp = RegularGridInterpolator( + (v_grid, yaw_grid_rad), tsr_tbl, + method="linear", bounds_error=False, fill_value=None + ) return pitch_interp, tsr_interp, turbine.rated_rotor_speed -def plot_pitch_tsr_vs_wind(wind_speeds, yaw_vals, pitch_tbl, tsr_tbl, pitch_in_rad=True): - sns.set_theme(style="whitegrid") - n_yaw = len(yaw_vals) - colors = sns.color_palette("viridis", n_colors=n_yaw) +def load_control_interps_from_csv(csv_path): + """ + Load wind/yaw control LUT CSV and return 2D interpolators. - fig, axes = plt.subplots(2, 1, figsize=(8, 8), sharex=True) + Expected CSV columns: + wind_speed_mps, yaw_rad, pitch_rad, tsr, gen_power + """ + data = np.genfromtxt(csv_path, delimiter=",", names=True) - # If stored in radians, convert to degrees for plotting - pitch_plot = np.rad2deg(pitch_tbl) if pitch_in_rad else pitch_tbl + ws = np.asarray(data["wind_speed_mps"], dtype=float) + yaw = np.asarray(data["yaw_rad"], dtype=float) + pitch = np.asarray(data["pitch_rad"], dtype=float) + tsr = np.asarray(data["tsr"], dtype=float) - # Plot one line per yaw - for j, yaw in enumerate(yaw_vals): - sns.lineplot( - x=wind_speeds, y=pitch_plot[:, j], - ax=axes[0], color=colors[j], linewidth=2 - ) - sns.lineplot( - x=wind_speeds, y=tsr_tbl[:, j], - ax=axes[1], color=colors[j], linewidth=2 - ) + v_grid = np.unique(ws) + yaw_grid = np.unique(yaw) - axes[0].set_ylabel("Pitch (deg)" if pitch_in_rad else "Pitch") - axes[0].set_title("Steady-State Pitch vs Wind Speed") + # sort rows by (ws, yaw), then reshape into [n_ws, n_yaw] + order = np.lexsort((yaw, ws)) + n_ws, n_yaw = len(v_grid), len(yaw_grid) - axes[1].set_xlabel("Wind Speed (m/s)") - axes[1].set_ylabel("TSR (-)") - axes[1].set_title("Steady-State TSR vs Wind Speed") + pitch_tbl = pitch[order].reshape(n_ws, n_yaw) + tsr_tbl = tsr[order].reshape(n_ws, n_yaw) - # One shared legend - legend_handles = [ - Line2D([0], [0], color=colors[j], lw=2, label=f"{yaw:g}°") - for j, yaw in enumerate(yaw_vals) - ] - fig.legend(handles=legend_handles, title="Yaw", loc="center right") - plt.tight_layout(rect=[0, 0, 0.88, 1]) # leave room for legend - plt.savefig("pitch_tsr_plots.png") + pitch_interp = RegularGridInterpolator( + (v_grid, yaw_grid), pitch_tbl, + method="linear", bounds_error=False, fill_value=None + ) + tsr_interp = RegularGridInterpolator( + (v_grid, yaw_grid), tsr_tbl, + method="linear", bounds_error=False, fill_value=None + ) + return pitch_interp, tsr_interp -# Example call: -# plot_pitch_tsr_vs_wind(U_grid, yaw_grid, pitch_tbl, tsr_tbl, pitch_in_rad=True) +# def query_control(pitch_interp, tsr_interp, ws, yaw_rad): +# pitch = query_pitch(pitch_interp, ws, yaw_rad) +# tsr = query_tsr(tsr_interp, ws, yaw_rad) +# return pitch, tsr -def rosco_pitch_interp(controller): - """ - Return 1D pitch interpolator from tuned ROSCO controller - - Args: - controller (rosco.toolbox.controller.Controller) +def query_controls(interp, ws, yaw_rad): """ - wind_table = controller.v - pitch_table = np.maximum(controller.pitch_op, controller.ps_min_bld_pitch) - return interp1d(wind_table, pitch_table, kind="linear", fill_value="extrapolate", bounds_error=False) + Vectorized query for 2D interpolator interp(ws, yaw). -def rosco_tsr_interp(controller): + Supports: + - scalar ws, scalar yaw -> float + - array ws, scalar yaw -> array + - scalar ws, array yaw -> array + - array ws, array yaw (broadcastable shapes, including same-length 1D pairwise) -> array """ - Return 1D tsr interpolator from tuned ROSCO controller - - Args: - controller (rosco.toolbox.controller.Controller) - """ - wind_table = controller.v - tsr_table = controller.TSR_op - return interp1d(wind_table, tsr_table, kind="linear", fill_value="extrapolate", bounds_error=False) + ws_arr = np.asarray(ws, dtype=float) + yaw_arr = np.asarray(yaw_rad, dtype=float) + + # Broadcast to common shape (or raise if incompatible) + ws_b, yaw_b = np.broadcast_arrays(ws_arr, yaw_arr) + + # Build points for RegularGridInterpolator: shape (N, 2) + pts = np.column_stack((ws_b.ravel(), yaw_b.ravel())) + # Vectorized interpolation + vals = np.asarray(interp(pts)).reshape(ws_b.shape) -deg2rad = np.deg2rad(1) -rad2deg = np.rad2deg(1) -rpm2RadSec = 2.0*(np.pi)/60.0 + # Return float for scalar input, ndarray otherwise + return float(vals) if vals.shape == () else vals +# ----------------------------- +# Steady-state simulation +# ----------------------------- def sim_ws_mitrotor( - sim, bem, ws, dt, init_tsr, init_pitch, - wd=0.0, yaw_init=0.0, - max_iter = 10000, tol = 1e-2, + sim, bem, ws, dt, init_tsr, init_pitch, + wd=0.0, yaw_init=0.0, + max_iter=20000, + conv_settings=None, + verbose=True, ): - # Store turbine data for convenience + """ + Steady-state single-wind-speed simulation (no time history storage), + with rolling-window convergence checks. + """ + if conv_settings is None: + conv_settings = ConvergenceSettings() + + # Turbine constants R = sim.turbine.rotor_radius rho = sim.turbine.rho - GBRatio = sim.turbine.Ng - - # Declare output arrays - bld_pitch = init_pitch * deg2rad - tsr = init_tsr - rot_speed = (tsr * ws / R) #rad / s - gen_speed = rot_speed * GBRatio - aero_torque = 1000.0 - gen_torque = 1.0 - gen_power = 0.0 - nac_yaw = yaw_init - nac_yawerr = 0.0 - nac_yawrate = 0.0 - - # Loop through time + Ng = sim.turbine.Ng + J = sim.turbine.J + gbox_eff = sim.turbine.GBoxEff / 100.0 + gen_eff = sim.turbine.GenEff / 100.0 + + # States + bld_pitch = np.deg2rad(init_pitch) # rad (init_pitch is deg) + rot_speed = (init_tsr * ws / R) # rad/s + gen_speed = rot_speed * Ng # rad/s + gen_torque = 0.0 # Nm + gen_power = 0.0 # W + nac_yaw = yaw_init # rad + nac_yawrate = 0.0 # rad/s + + # Convergence tracker + tracker = init_convergence_tracker(dt, conv_settings) + n_iter = 0 t = 0.0 + converged = False + last_metrics = None + # begin iteration while n_iter < max_iter: t += dt - tsr = rot_speed * R / ws - gamma = wd - nac_yaw - sol = bem(bld_pitch, tsr, yaw = gamma) - cp = sol.Cp() - - # Update the turbine state - # -- 1DOF model: rotor speed and generator speed (scaled by Ng) - aero_torque = 0.5 * rho * (np.pi * R**3) * (cp/tsr) * ws**2 - rot_speed = rot_speed + (dt/sim.turbine.J)*(aero_torque - sim.turbine.Ng * gen_torque / (sim.turbine.GBoxEff/100)) - gen_speed = rot_speed * sim.turbine.Ng - - # populate turbine state dictionary - turbine_state = {} - turbine_state['iStatus'] = 1 - turbine_state['t'] = t - turbine_state['dt'] = dt - turbine_state['ws'] = ws - turbine_state['bld_pitch'] = bld_pitch - turbine_state['gen_torque'] = gen_torque - turbine_state['gen_speed'] = gen_speed - turbine_state['gen_eff'] = sim.turbine.GenEff/100 - turbine_state['rot_speed'] = rot_speed - turbine_state['Yaw_fromNorth'] = nac_yaw - turbine_state['Y_MeasErr'] = gamma - - # Define outputs + + # aero side + tsr = rot_speed * R / max(ws, 1e-6) + + # yaw misalignment for aero + yaw_err = wd - nac_yaw + + # BEM call + sol = bem( + bld_pitch, tsr, + yaw = yaw_err, + tilt = 0.0 + ) + cp = float(np.ravel(sol.Cp())[0]) + + # 1DOF rotor dynamics (same structure as ROSCO Sim) + aero_torque = 0.5 * rho * (np.pi * R**3) * (cp / max(tsr, 1e-6)) * ws**2 + rot_speed = rot_speed + (dt / J) * (aero_torque - Ng * gen_torque / gbox_eff) + gen_speed = rot_speed * Ng + + # Controller input state + turbine_state = { + "iStatus": 1, + "t": t, + "dt": dt, + "ws": ws, + "bld_pitch": bld_pitch, + "gen_torque": gen_torque, + "gen_speed": gen_speed, + "gen_eff": gen_eff, + "rot_speed": rot_speed, + "Yaw_fromNorth": nac_yaw, + "Y_MeasErr": yaw_err, + } + + # Controller outputs gen_torque, bld_pitch, nac_yawrate = sim.controller_int.call_controller(turbine_state) - # Calculate the power - gen_power_old = gen_power - gen_power = gen_speed * gen_torque * sim.turbine.GenEff / 100 - # Calculate the nacelle position + # Power + gen_power = gen_speed * gen_torque * gen_eff # W + + # Yaw dynamics nac_yaw += nac_yawrate * dt - if (gen_power_old - gen_power < tol) and (n_iter > 60 / dt): - print(f"Converged after {n_iter} with Power: {gen_power} kW") + # Convergence tracking + update_convergence_tracker(tracker, gen_power, rot_speed, bld_pitch) + converged, metrics = check_convergence(n_iter, dt, tracker, conv_settings) + if metrics is not None: + last_metrics = metrics + + # Check if converged + if converged: + if verbose and last_metrics is not None: + print( + f"Converged after {n_iter} steps " + f"(t={n_iter*dt:.1f}s): " + f"P={last_metrics['p_mean']/1000:.1f} kW, " + f"std(P)/mean(P)={last_metrics['rel_p_std']:.2e}, " + f"max|dω/dt|={last_metrics['max_domega_dt']:.2e} rad/s², " + f"max|dθ/dt|={np.rad2deg(last_metrics['max_dpitch_dt']):.2e} deg/s" + ) break + n_iter += 1 + if not converged and verbose: + print(f"WARNING: hit max_iter={max_iter} without convergence") + # Kill controller sim.controller_int.kill_discon() - # Save these values - sim.bld_pitch = bld_pitch - sim.tsr = rot_speed * R / ws - # self.rot_speed = rot_speed - # self.gen_speed = gen_speed - # self.aero_torque = aero_torque - # self.gen_torque = gen_torque - # self.gen_power = gen_power - # self.ws = ws - # self.wd = wd - # self.nac_yaw = nac_yaw - - -# from rosco.toolbox.control_interface import ControllerInterface -# # ------------------------------------------------------------- -# # Try generating 2D lookup table with ROSCO!! -# # ------------------------------------------------------------- - -# def _parse_rosco_outputs(out): -# """ -# Handle slight API differences in ROSCO toolbox versions. -# Expected: pitch command (rad, collective) and generator torque command (N-m). -# """ -# # dict-like -# if isinstance(out, dict): -# if "bld_pitch_cmd" in out: -# beta_cmd = np.atleast_1d(out["bld_pitch_cmd"])[0] -# elif "pitch_cmd" in out: -# beta_cmd = np.atleast_1d(out["pitch_cmd"])[0] -# else: -# raise KeyError("Could not find pitch command in ROSCO output dict.") - -# if "gen_torque_cmd" in out: -# Tg_cmd = out["gen_torque_cmd"] -# elif "torque_cmd" in out: -# Tg_cmd = out["torque_cmd"] -# else: -# raise KeyError("Could not find torque command in ROSCO output dict.") -# return float(beta_cmd), float(Tg_cmd) - -# # tuple/list-like fallback -# if isinstance(out, (tuple, list)) and len(out) >= 2: -# beta_cmd = np.atleast_1d(out[0])[0] -# Tg_cmd = out[1] -# return float(beta_cmd), float(Tg_cmd) - -# raise TypeError("Unknown ROSCO controller return type.") - - -# def _call_rosco(ci, t, dt, beta, omega, Tg, Ng, U_meas): -# """ -# Version-tolerant ROSCO call wrapper. -# You may need to tweak keyword names once for your installed ROSCO version. -# """ -# # Try common signature 1 -# try: -# out = ci.call_controller( -# t=t, -# dt=dt, -# bld_pitch=np.array([beta, beta, beta]), -# gen_speed=omega * Ng, -# gen_torque=Tg, -# rot_speed=omega, -# wind_speed=U_meas, -# ) -# return _parse_rosco_outputs(out) -# except TypeError: -# pass - -# # Try common signature 2 -# out = ci.call_controller( -# t, dt, -# np.array([beta, beta, beta]), -# omega * Ng, -# Tg, -# omega, -# U_meas, -# ) -# return _parse_rosco_outputs(out) - - -# def generate_rosco_2d_tables_full_rosco( -# rosco_yaml, -# bem, -# wind_table, -# yaw_table, -# discon_lib_path, # compiled ROSCO shared lib (e.g., libdiscon.so / discon.dll) -# discon_in_path, # DISCON.IN from ROSCO tuning -# TurbineName="IEA15MW", -# GenEff=95.756, -# generator_inertia=1836784, -# dt=0.05, -# t_max=220.0, -# tilt_deg=5.0, -# min_ws=0.25, -# omega_eps=0.2, -# tau_pitch=0.35, -# tau_torque=0.20, -# pitch_rate_max=np.deg2rad(8.0), -# torque_rate_max=3e6, -# t_min_check=20.0, -# conv_window=4.0, -# avg_window=5.0, -# tol_omega=2e-3, -# tol_pitch=np.deg2rad(0.03), -# tol_torque=2e4, -# save_npz=None, -# ): -# """ -# Fully ROSCO-controlled trim-map generation (no hand-coded region logic). -# """ -# # Load turbine properties via your existing pipeline -# inps = load_rosco_yaml(rosco_yaml) -# turbine = ROSCO_turbine.Turbine(inps["turbine_params"]) -# turbine = load_from_mitrotor( -# turbine, bem, -# TurbineName=TurbineName, -# GenEff=GenEff, -# generator_inertia=generator_inertia, -# yaw=0.0, -# ) - -# # For initialization only (NOT control logic) -# pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( -# rosco_yaml, bem, -# TurbineName=TurbineName, GenEff=GenEff, generator_inertia=generator_inertia -# ) - -# # ROSCO DLL interface -# ci = ControllerInterface(discon_lib_path, discon_in_path) - -# R = float(bem.rotor.R) -# A = np.pi * R**2 -# rho = float(turbine.rho) -# Ng = float(turbine.Ng) -# J = float(turbine.J) - -# gbox_eff = float(turbine.GBoxEff) -# if gbox_eff > 1.5: # percent -> fraction -# gbox_eff /= 100.0 -# gbox_eff = np.clip(gbox_eff, 1e-3, 1.0) - -# wind_table = np.asarray(wind_table, dtype=float) -# yaw_table = np.asarray(yaw_table, dtype=float) - -# nW, nY = len(wind_table), len(yaw_table) -# tabs = { -# "wind_table": wind_table, -# "yaw_table": yaw_table, -# "pitch": np.zeros((nW, nY)), -# "omega": np.zeros((nW, nY)), -# "tsr_bem": np.zeros((nW, nY)), -# "tsr_normal": np.zeros((nW, nY)), -# "Cp": np.zeros((nW, nY)), -# "Ct": np.zeros((nW, nY)), -# "a": np.zeros((nW, nY)), -# "power": np.zeros((nW, nY)), -# "converged": np.zeros((nW, nY), dtype=bool), -# } - -# n_steps = int(t_max / dt) -# n_conv = max(3, int(conv_window / dt)) -# n_avg = max(3, int(avg_window / dt)) - -# for j, yaw_deg in enumerate(yaw_table): -# yaw = np.deg2rad(yaw_deg) -# tilt = np.deg2rad(tilt_deg) - -# # warm start along wind -# state = None - -# for i, U_in in enumerate(wind_table): -# U = max(float(U_in), min_ws) -# U_n = max(U * np.cos(yaw) * np.cos(tilt), min_ws) - -# # init state -# if state is None: -# lam0 = max(float(tsr_interp(U_n)), 0.1) -# omega = max(lam0 * U_n / R, omega_eps) -# beta = float(pitch_interp(U_n)) -# Tg = float(turbine.rated_torque * (omega / max(rated_rotor_speed, 1e-3))**2) -# else: -# omega, beta, Tg = state["omega"], state["beta"], state["Tg"] - -# omega_hist, beta_hist, Tg_hist = [], [], [] -# cp_hist, ct_hist, a_hist = [], [], [] -# converged = False - -# for k in range(n_steps): -# t = k * dt -# omega = max(omega, omega_eps) - -# # --- ROSCO gives commands (fully controller-managed) --- -# beta_cmd, Tg_cmd = _call_rosco( -# ci=ci, t=t, dt=dt, -# beta=beta, omega=omega, Tg=Tg, Ng=Ng, -# U_meas=U_n, # rotor-normal measured wind -# ) - -# # actuator dynamics / limits (plant-side, not control policy) -# dbeta = np.clip((beta_cmd - beta) / tau_pitch, -pitch_rate_max, pitch_rate_max) -# dTg = np.clip((Tg_cmd - Tg) / tau_torque, -torque_rate_max, torque_rate_max) -# beta += dbeta * dt -# Tg += dTg * dt - -# # MITRotor aero -# tsr_bem = omega * R / U -# sol = bem( -# np.array([beta]), -# np.array([tsr_bem]), -# yaw=np.array([yaw]), -# tilt=np.array([tilt]), -# ) -# Cp = float(sol.Cp()[0]) -# Ct = float(sol.Ct()[0]) -# a = float(sol.a()[0]) - -# P = 0.5 * rho * A * Cp * U**3 -# Qaero = P / max(omega, omega_eps) -# Qgen_rotor = Tg * Ng / gbox_eff -# domega = (Qaero - Qgen_rotor) / J -# omega = max(omega + domega * dt, omega_eps) - -# omega_hist.append(omega) -# beta_hist.append(beta) -# Tg_hist.append(Tg) -# cp_hist.append(Cp) -# ct_hist.append(Ct) -# a_hist.append(a) - -# if t >= t_min_check and len(omega_hist) >= n_conv: -# if (np.ptp(omega_hist[-n_conv:]) < tol_omega and -# np.ptp(beta_hist[-n_conv:]) < tol_pitch and -# np.ptp(Tg_hist[-n_conv:]) < tol_torque): -# converged = True -# break - -# # steady averages -# omega_ss = float(np.mean(omega_hist[-n_avg:])) -# beta_ss = float(np.mean(beta_hist[-n_avg:])) -# Cp_ss = float(np.mean(cp_hist[-n_avg:])) -# Ct_ss = float(np.mean(ct_hist[-n_avg:])) -# a_ss = float(np.mean(a_hist[-n_avg:])) - -# tabs["pitch"][i, j] = beta_ss -# tabs["omega"][i, j] = omega_ss -# tabs["tsr_bem"][i, j] = omega_ss * R / U -# tabs["tsr_normal"][i, j] = omega_ss * R / U_n -# tabs["Cp"][i, j] = Cp_ss -# tabs["Ct"][i, j] = Ct_ss -# tabs["a"][i, j] = a_ss -# tabs["power"][i, j] = 0.5 * rho * A * Cp_ss * U**3 -# tabs["converged"][i, j] = converged - -# state = {"omega": omega, "beta": beta, "Tg": Tg} - -# if not converged: -# print(f"[warn] not converged at U={U:.2f}, yaw={yaw_deg:.2f}") - -# if save_npz is not None: -# np.savez(save_npz, **tabs) - -# return tabs + # Save outputs + sim.bld_pitch = bld_pitch # rad + sim.tsr = rot_speed * R / max(ws, 1e-6) + sim.rot_speed = rot_speed # rad/s + sim.gen_speed = gen_speed # rad/s + sim.gen_torque = gen_torque # Nm + sim.gen_power = gen_power # W + sim.nac_yaw = nac_yaw # rad + sim.n_iter = n_iter + sim.converged = converged + + return converged + class WarmStartControllerInterface(ROSCO_ci.ControllerInterface): + """ + ROSCO controller interface with configurable warm-start initial conditions. + + This subclass overrides the default `ControllerInterface` initialization so + the first DISCON call (`iStatus=0`) is seeded with user-provided initial + wind speed, rotor/generator speeds, pitch, torque, and nacelle IMU angle, + instead of hard-coded defaults. + + Notes + ----- + - This is useful for steady-state sweeps, where reducing startup transients + improves convergence speed and robustness. + - Units are expected to match ROSCO avrSWAP channel conventions. + """ + def __init__( self, lib_name, param_filename="DISCON.IN", init_ws=10.0, # m/s - init_rot_speed=1.0, # rad/s (LSS) - init_gen_speed=1.0, # rad/s (HSS) + init_rot_speed=1.0, # rad/s + init_gen_speed=1.0, # rad/s init_pitch_deg=0.0, # deg init_torque=0.0, # Nm init_nac_imu=0.0, # rad **kwargs ): + """ + Initialize warm-start settings and construct the ROSCO controller interface. + + Parameters + ---------- + lib_name : str + Path to the ROSCO dynamic library (.dll/.so/.dylib). + param_filename : str, optional + Path to DISCON input file, by default "DISCON.IN". + init_ws : float, optional + Initial wind speed used during DISCON init, in m/s. + init_rot_speed : float, optional + Initial low-speed shaft rotor speed, in rad/s. + init_gen_speed : float, optional + Initial generator speed (high-speed shaft), in rad/s. + init_pitch_deg : float, optional + Initial collective blade pitch, in degrees. + init_torque : float, optional + Initial generator torque, in Nm. + init_nac_imu : float, optional + Initial nacelle IMU angle/state, in radians. + **kwargs + Additional keyword arguments forwarded to + `ROSCO_ci.ControllerInterface` (e.g., `DT`, `sim_name`, etc.). + """ self.init_ws = float(init_ws) self.init_rot_speed = float(init_rot_speed) self.init_gen_speed = float(init_gen_speed) @@ -665,6 +529,18 @@ def __init__( ) def init_discon(self): + """ + Initialize DISCON with warm-start avrSWAP values. + + This method allocates and populates the avrSWAP array, sets the first-call + status (`iStatus=0`), invokes DISCON once to initialize internal ROSCO states, + then switches to normal run mode (`iStatus=1`) for subsequent calls. + + Raises + ------ + ValueError + If ROSCO returns a negative `aviFAIL` error code during initialization. + """ self.torque = self.init_torque # Load library + allocate swap @@ -683,7 +559,7 @@ def init_discon(self): self.avrSWAP[22] = self.init_torque # gen torque [Nm] # Initial blade pitch (all blades) - pitch_rad = self.pitch * np.deg2rad(1.0) + pitch_rad = np.deg2rad(self.pitch) self.avrSWAP[3] = pitch_rad self.avrSWAP[32] = pitch_rad self.avrSWAP[33] = pitch_rad @@ -716,6 +592,179 @@ def init_discon(self): if self.aviFAIL.value < 0: raise ValueError("ROSCO dynamic library has returned an error") - +# ----------------------------- +# Convergence helper structures +# ----------------------------- +@dataclass +class ConvergenceSettings: + """ + Tunable parameters for steady-state convergence detection. + + Attributes + ---------- + warmup_time : float + Time to ignore before evaluating convergence, in seconds. + window_time : float + Length of rolling analysis window, in seconds. + hold_time : float + Duration for which all criteria must remain satisfied, in seconds. + tol_rel_power_std : float + Threshold on relative power variability: std(P)/|mean(P)|. + tol_domega_dt : float + Threshold on max rotor acceleration magnitude, in rad/s^2. + tol_dpitch_dt : float + Threshold on max pitch-rate magnitude, in rad/s. + """ + warmup_time: float = 60.0 + window_time: float = 20.0 + hold_time: float = 5.0 + tol_rel_power_std: float = 1e-3 + tol_domega_dt: float = 1e-4 + tol_dpitch_dt: float = np.deg2rad(1e-3) + + +def init_convergence_tracker(dt: float, settings: ConvergenceSettings): + """ + Create and initialize rolling-window state for convergence checks. + + Parameters + ---------- + dt : float + Simulation timestep in seconds. + settings : ConvergenceSettings + Convergence timing and tolerance settings. + + Returns + ------- + dict + Tracker containing step counts, rolling histories, and stable counter. + Keys include: `warmup_steps`, `window_steps`, `hold_steps`, + `stable_count`, `p_hist`, `omega_hist`, `pitch_hist`. + """ + warmup_steps = int(np.ceil(settings.warmup_time / dt)) + window_steps = int(np.ceil(settings.window_time / dt)) + hold_steps = int(np.ceil(settings.hold_time / dt)) + + tracker = { + "warmup_steps": warmup_steps, + "window_steps": window_steps, + "hold_steps": hold_steps, + "stable_count": 0, + "p_hist": deque(maxlen=window_steps), # W + "omega_hist": deque(maxlen=window_steps), # rad/s + "pitch_hist": deque(maxlen=window_steps), # rad + } + return tracker + + +def update_convergence_tracker(tracker, gen_power, rot_speed, bld_pitch): + """ + Append latest simulation values to rolling convergence histories. + + Parameters + ---------- + tracker : dict + Tracker dictionary created by `init_convergence_tracker`. + gen_power : float + Generator electrical power, in W. + rot_speed : float + Rotor speed, in rad/s. + bld_pitch : float + Collective blade pitch, in rad. + """ + tracker["p_hist"].append(float(gen_power)) + tracker["omega_hist"].append(float(rot_speed)) + tracker["pitch_hist"].append(float(bld_pitch)) + + +def compute_window_metrics(tracker, dt): + """ + Compute window-based convergence metrics from rolling histories. + + Parameters + ---------- + tracker : dict + Convergence tracker containing `p_hist`, `omega_hist`, `pitch_hist`. + dt : float + Simulation timestep in seconds. + + Returns + ------- + dict + Dictionary with: + - `p_mean` : mean power over window [W] + - `rel_p_std` : relative power std, std(P)/max(|mean(P)|, 1) + - `max_domega_dt` : max |d(omega)/dt| over window [rad/s^2] + - `max_dpitch_dt` : max |d(pitch)/dt| over window [rad/s] + """ + p = np.asarray(tracker["p_hist"]) + om = np.asarray(tracker["omega_hist"]) + th = np.asarray(tracker["pitch_hist"]) + + p_mean = float(np.mean(p)) + rel_p_std = float(np.std(p) / max(abs(p_mean), 1.0)) + max_domega_dt = float(np.max(np.abs(np.diff(om))) / dt) + max_dpitch_dt = float(np.max(np.abs(np.diff(th))) / dt) + + return { + "p_mean": p_mean, + "rel_p_std": rel_p_std, + "max_domega_dt": max_domega_dt, + "max_dpitch_dt": max_dpitch_dt, + } + + +def check_convergence(n_iter, dt, tracker, settings: ConvergenceSettings): + """ + Evaluate steady-state convergence criteria. + + Criteria + -------- + After warmup and once the rolling window is full, convergence is considered + satisfied at a given step if: + 1) relative power std < `tol_rel_power_std` + 2) max rotor acceleration < `tol_domega_dt` + 3) max pitch rate < `tol_dpitch_dt` + + These conditions must hold for `hold_steps` consecutive evaluations. + + Parameters + ---------- + n_iter : int + Current simulation iteration index. + dt : float + Simulation timestep in seconds. + tracker : dict + Convergence tracker dictionary. + settings : ConvergenceSettings + Convergence timing and tolerance settings. + + Returns + ------- + tuple[bool, dict | None] + `(converged, metrics)` where: + - `converged` is True if hold condition is met. + - `metrics` is None until checks become active; otherwise window metrics + from `compute_window_metrics`. + """ + # not ready yet + if n_iter < tracker["warmup_steps"]: + return False, None + if len(tracker["p_hist"]) < tracker["window_steps"]: + return False, None + + metrics = compute_window_metrics(tracker, dt) + + ok_power = metrics["rel_p_std"] < settings.tol_rel_power_std + ok_omega = metrics["max_domega_dt"] < settings.tol_domega_dt + ok_pitch = metrics["max_dpitch_dt"] < settings.tol_dpitch_dt + + if ok_power and ok_omega and ok_pitch: + tracker["stable_count"] += 1 + else: + tracker["stable_count"] = 0 + + converged = tracker["stable_count"] >= tracker["hold_steps"] + return converged, metrics \ No newline at end of file diff --git a/MITRotor/FlorisInterface/ROSCOUtilities.py b/MITRotor/FlorisInterface/ROSCOUtilities.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index d6b1cc4..99d2d38 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -8,6 +8,7 @@ import pandas as pd import polars as pl from scipy.interpolate import interp1d +import time # FLORIS modules from floris import FlorisModel, TimeSeries @@ -21,7 +22,7 @@ from MITRotor.Momentum import UnifiedMomentumLUT from MITRotor import BEM, BEMGeometry, IEA15MW from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp -from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps +from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls figdir = Path("fig") @@ -41,11 +42,11 @@ def change_control_param(param_key, param_value, template_yaml, bem): pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps(temp_yaml, bem) return pitch_interp, tsr_interp, rated_rotor_speed -def get_turbine_power_coefficent(bem, fmodel, wind_speeds): - rotor_area = np.pi * bem.rotor.R**2 +def get_turbine_power_coefficent(fturbine, fmodel, wind_speeds): + rotor_area = np.pi * fturbine.bem_model.rotor.R**2 floris_power = np.squeeze(fmodel.get_turbine_powers()) - floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) - return floris_Cp, floris_power + floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3 * fturbine.eff_ratio) + return floris_Cp, floris_power / 1e6 # MW def main(): # wind condtions @@ -67,7 +68,8 @@ def main(): abbas_pitch_interp = interp1d(abbas_pitch["x"], abbas_pitch["y"], kind="linear", fill_value="extrapolate", bounds_error=False) abbas_tsr_interp = interp1d(abbas_tsr["x"], abbas_tsr["y"], kind="linear", fill_value="extrapolate", bounds_error=False) - # # create new MITRotor BEM model with a LUT for UMM + # create new MITRotor BEM model with a LUT for UMM + print("Generating new LUT for BEM.") cache_dir = Path("cache") cache_dir.mkdir(exist_ok=True, parents=True) cache_file = cache_dir / "lut.csv" @@ -75,23 +77,30 @@ def main(): cache_fn=cache_file, regenerate=False, LUT_Cts=np.linspace(-0.5,1.5,40), - LUT_yaws=np.linspace(0.0,25.1,25), + LUT_yaws=np.linspace(0.0,40.0,40), ) + print("LUT for BEM done generating. ") bem = BEM(rotor = IEA15MW(), momentum_model = lut_model, geometry = BEMGeometry(Nr=10, Ntheta=20)) - # # Load IEA15MW ROSCO parameters to make controllers + # Load IEA15MW ROSCO parameters to make controllers + start = time.time() rosco_yaml_PS_Mode_3 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" - rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp, rosco_PS_Mode_3_rated_rotorspeed = get_rosco_control_interps(rosco_yaml_PS_Mode_3, bem) + rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp, rosco_PS_Mode_3_rated_rotorspeed = get_rosco_control_interps( + rosco_yaml_PS_Mode_3, bem, + regenerate = False, save_control_file = "control.csv") + end = time.time() + print(f"Time to make control CSV: {end - start}") + # rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param("PS_Mode", 0, rosco_yaml_PS_Mode_3, bem) # Plot IEA15MW control from ROSCO paper, ROSOC control with PS_Mode = 3, and ROSOC control with PS_Mode = 0 pitch_abbas = abbas_pitch_interp(wind_speeds) # pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) - pitch_ps3 = np.rad2deg(rosco_PS_Mode_3_pitch_interp(wind_speeds)) + pitch_ps3 = np.rad2deg(query_controls(rosco_PS_Mode_3_pitch_interp, wind_speeds, 0.0)) tsr_abbas = abbas_tsr_interp(wind_speeds) # tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) - tsr_ps3 = rosco_PS_Mode_3_tsr_interp(wind_speeds) + tsr_ps3 = query_controls(rosco_PS_Mode_3_tsr_interp, wind_speeds, 0.0) # Create figure fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) @@ -105,7 +114,6 @@ def main(): ax[0].set_ylabel("Pitch [deg]") ax[0].set_title("Pitch Schedule") ax[0].grid(True) - # ax[0].legend() # Plot TSR # ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) @@ -121,16 +129,16 @@ def main(): plt.savefig(figdir / "example_8_IEA15mw_controls.png", dpi=300) # make FLORIS turbines - floris_default_turbine = MITRotorTurbine( - bem_model = bem, - ) + # floris_default_turbine = MITRotorTurbine( + # bem_model = bem, + # ) - floris_abbas_turbine = MITRotorTurbine( - bem_model = bem, - pitch_interp = abbas_pitch_interp, - pitch_rad = False, - tsr_interp = abbas_tsr_interp, - ) + # floris_abbas_turbine = MITRotorTurbine( + # bem_model = bem, + # pitch_interp = abbas_pitch_interp, + # pitch_rad = False, + # tsr_interp = abbas_tsr_interp, + # ) # floris_PS_Mode_0_turbine = MITRotorTurbine( # bem_model = bem, @@ -149,19 +157,19 @@ def main(): ) yaw = 0.0 # degrees yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] - fmodel_default = FlorisModel("defaults") - fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_default.set_operation_model(floris_default_turbine) - fmodel_default.run() - Ct_default = fmodel_default.get_turbine_thrust_coefficients() - Cp_default, P_default = get_turbine_power_coefficent(bem, fmodel_default, wind_speeds) + # fmodel_default = FlorisModel("defaults") + # fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + # fmodel_default.set_operation_model(floris_default_turbine) + # fmodel_default.run() + # Ct_default = fmodel_default.get_turbine_thrust_coefficients() + # Cp_default, P_default = get_turbine_power_coefficent(floris_default_turbine, fmodel_default, wind_speeds) - fmodel_abbas = FlorisModel("defaults") - fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_abbas.set_operation_model(floris_abbas_turbine) - fmodel_abbas.run() - Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() - Cp_abbas, P_abbas = get_turbine_power_coefficent(bem, fmodel_abbas, wind_speeds) + # fmodel_abbas = FlorisModel("defaults") + # fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + # fmodel_abbas.set_operation_model(floris_abbas_turbine) + # fmodel_abbas.run() + # Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() + # Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) # fmodel_PS_Mode_0 = FlorisModel("defaults") @@ -169,26 +177,26 @@ def main(): # fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) # fmodel_PS_Mode_0.run() # Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() - # Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_0, wind_speeds) + # Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) fmodel_PS_Mode_3 = FlorisModel("defaults") fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) fmodel_PS_Mode_3.run() Ct_PS_Mode_3 = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() - Cp_PS_Mode_3, P_PS_Mode_3 = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) + Cp_PS_Mode_3, P_PS_Mode_3 = get_turbine_power_coefficent(floris_PS_Mode_3_turbine, fmodel_PS_Mode_3, wind_speeds) # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (16,4), constrained_layout=True) - fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = 0 for Different Control Strategies") - ax1.plot( - wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", - lw=3, linestyle = "solid", zorder = 1, - ) - ax1.plot( - wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", - lw=3, linestyle = "solid", zorder = 1, - ) + fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = {yaw} for Different Control Strategies") + # ax1.plot( + # wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", + # lw=3, linestyle = "solid", zorder = 1, + # ) + # ax1.plot( + # wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", + # lw=3, linestyle = "solid", zorder = 1, + # ) # ax1.plot( # wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", # lw=3, linestyle = "dashed", zorder = 1, @@ -200,16 +208,16 @@ def main(): ax1.set_ylabel("$C_T [-]$") ax1.set_title("$C_T$") ax1.grid(True) - # ax1.legend() + ax1.legend() - ax2.plot( - wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", - lw=3, linestyle = "solid", zorder = 1, - ) - ax2.plot( - wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", - lw=3, linestyle = "solid", zorder = 1, - ) + # ax2.plot( + # wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", + # lw=3, linestyle = "solid", zorder = 1, + # ) + # ax2.plot( + # wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", + # lw=3, linestyle = "solid", zorder = 1, + # ) # ax2.plot( # wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", # lw=3, linestyle = "dashed", zorder = 1, @@ -221,23 +229,24 @@ def main(): ax2.set_ylabel("$C_P [-]$") ax2.set_title("$C_P$") ax2.grid(True) - # ax2.legend() + ax2.legend() - ax3.plot( - wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", - lw=3, linestyle = "solid", zorder = 1, - ) - ax3.plot( - wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", - lw=3, linestyle = "solid", zorder = 1, - ) # ax3.plot( - # wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - # lw=3, linestyle = "dashed", zorder = 1, + # wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", + # lw=3, linestyle = "solid", zorder = 1, + # ) + # ax3.plot( + # wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", + # lw=3, linestyle = "solid", zorder = 1, # ) + # ax3.plot( + # # wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + # # lw=3, linestyle = "dashed", zorder = 1, + # # ) ax3.plot(wind_speeds, P_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) + ax3.axhline(y = 15, lw=3, linestyle = "dotted", zorder = 0, color = "k", label = "15MW") ax3.set_xlabel("Wind Speed [m/s]") ax3.set_ylabel("$Power [MW]$") ax3.set_title("$Power$") @@ -246,118 +255,47 @@ def main(): plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) - # # plot the difference in CT/CP curves for different yaw values - # yaw_list = [0.0, 10.0, 20.0] # degrees - # fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) - # fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: PS_Mode = 3") - # for (i, yaw) in enumerate(yaw_list): - # yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] - # fmodel_PS_Mode_3 = FlorisModel("defaults") - # fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - # fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) - # fmodel_PS_Mode_3.run() - # ct = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() - # cp, p = get_turbine_power_coefficent(bem, fmodel_PS_Mode_3, wind_speeds) - - # ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax3.plot(wind_speeds, p, label=fr"Yaw = ${yaw}^\circ$", - # lw=3, linestyle = "solid", zorder = 1, - # ) - - # ax1.set_xlabel("Wind Speed [m/s]") - # ax1.set_ylabel("$C_T [-]$") - # ax1.set_title("$C_T$") - # ax1.grid(True) - - # ax2.set_xlabel("Wind Speed [m/s]") - # ax2.set_ylabel("$C_P [-]$") - # ax2.set_title("$C_P$") - # ax2.grid(True) - - # ax3.set_xlabel("Wind Speed [m/s]") - # ax3.set_ylabel("$Power [MW]$") - # ax3.set_title("$Power$") - # ax3.grid(True) - # ax3.legend() - # plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) - - # VALUES FROM THE LAST YAW EXAMPLE - # yaw_angles = [0.0, 10.0, 20.0] - # wind_speeds = np.array([ 2.99013218, 3.90378368, 4.81743518, 5.73108668, 6.64473818, 7.55838968, - # 8.47204118, 9.38569268, 10.29934418, 11.21299568, 12.12664717, 13.04029867, - # 13.95395017, 14.86760167, 15.78125317, 16.69490467, 17.60855617, 18.52220767, - # 19.43585917, 20.34951067, 21.26316217, 22.17681367, 23.09046517, 24.00411667, - # 24.91776817]) - - # pitch_data = [ - # np.array([0.06674022, 0.05708731, 0.04527502, 0.02821344, 0.00638814, 0., - # 0., 0., 0.03561096, 0.06201665, 0.10170293, 0.14064172, - # 0.17480852, 0.20334416, 0.2279438, 0.24969219, 0.26945148, 0.28830328, - # 0.3064061, 0.32385969, 0.34076384, 0.35709961, 0.37304778, 0.38862888, - # 0.40381301]), - # np.array([0.0670117, 0.05749029, 0.04596395, 0.02940459, 0.00804692, 0., - # 0., 0., 0.03159737, 0.05959471, 0.09666413, 0.13512453, - # 0.17020744, 0.19918221, 0.22414017, 0.2461998, 0.26590456, 0.2847307, - # 0.30278677, 0.32017919, 0.33707697, 0.35336143, 0.3692476, 0.38476091, - # 0.39988875]), - # np.array([0.06782725, 0.05861179, 0.0480336, 0.03267438, 0.01290243, 0., - # 0., 0., 0.01790879, 0.05231887, 0.08152841, 0.11886783, - # 0.15571155, 0.18608686, 0.21210147, 0.23480731, 0.25495804, 0.27378792, - # 0.29175, 0.30904482, 0.32577372, 0.34195922, 0.35764598, 0.37297828, - # 0.38797132]) - # ] - - # tsr_data = [ - # np.array([21.17700633, 16.24293034, 13.15445983, 11.05613061, 9.53582497, 9., - # 9., 9., 9., 8.54102737, 7.89840549, 7.34547759, - # 6.86473567, 6.44293918, 6.06989257, 5.73761929, 5.43979028, 5.17132019, - # 4.92807656, 4.7066669, 4.50428035, 4.31856823, 4.14761354, 3.98985351, - # 3.84362968]), - # np.array([21.36151077, 16.39563759, 13.28451444, 11.1591271, 9.62802523, 9., - # 9., 9., 9., 8.62614707, 7.97636669, 7.41738871, - # 6.93146656, 6.50518492, 6.12821732, 5.79248716, 5.49158768, 5.22037222, - # 4.97523891, 4.7520206, 4.54791367, 4.36057184, 4.18801658, 4.02856807, - # 3.88079097]), - # np.array([21.91578937, 16.88295332, 13.67521769, 11.49774122, 9.91488218, 9.00015098, - # 9., 9., 9., 8.88185921, 8.21215035, 7.63791414, - # 7.13816236, 6.6993949, 6.31116194, 5.96525606, 5.65514567, 5.37646321, - # 5.12399624, 4.89401575, 4.6836678, 4.49055784, 4.31266275, 4.14835247, - # 3.99643498]) - # ] - - # # Create figure - # fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 5)) - - # # Colors for yaw angles - # colors = plt.cm.viridis(np.linspace(0, 1, len(yaw_angles))) - - # # Plot pitch vs wind speed - # for i, yaw in enumerate(yaw_angles): - # ax1.plot(wind_speeds, np.rad2deg(pitch_data[i]), marker='o', linewidth=2, - # label=f'Yaw = {yaw}°', color=colors[i]) - # ax1.set_xlabel('Wind Speed (m/s)', fontsize=12) - # ax1.set_ylabel('Pitch Angle (deg)', fontsize=12) - # ax1.set_title('Pitch vs Wind Speed', fontsize=13, fontweight='bold') - # ax1.legend() - # ax1.grid(True, alpha=0.3) - - # # Plot TSR vs wind speed - # for i, yaw in enumerate(yaw_angles): - # ax2.plot(wind_speeds, tsr_data[i], marker='s', linewidth=2, - # label=f'Yaw = {yaw}°', color=colors[i]) - # ax2.set_xlabel('Wind Speed (m/s)', fontsize=12) - # ax2.set_ylabel('Tip Speed Ratio', fontsize=12) - # ax2.set_title('TSR vs Wind Speed', fontsize=13, fontweight='bold') - # ax2.legend() - # ax2.grid(True, alpha=0.3) - - # plt.tight_layout() - # plt.savefig(figdir / "example_8_IEA15mw_setpoints_yawed.png", dpi=300) + # plot the difference in CT/CP curves for different yaw values + yaw_list = [0.0, 10.0, 20.0] # degrees + fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) + fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: PS_Mode = 3") + for (i, yaw) in enumerate(yaw_list): + yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] + fmodel_PS_Mode_3 = FlorisModel("defaults") + fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) + fmodel_PS_Mode_3.run() + ct = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() + cp, p = get_turbine_power_coefficent(floris_PS_Mode_3_turbine, fmodel_PS_Mode_3, wind_speeds) + + ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot(wind_speeds, p, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + + ax1.set_xlabel("Wind Speed [m/s]") + ax1.set_ylabel("$C_T [-]$") + ax1.set_title("$C_T$") + ax1.grid(True) + + ax2.set_xlabel("Wind Speed [m/s]") + ax2.set_ylabel("$C_P [-]$") + ax2.set_title("$C_P$") + ax2.grid(True) + + ax3.axhline(y = 15, lw=3, linestyle = "dotted", zorder = 0, color = "k", label = "15MW") + ax3.set_xlabel("Wind Speed [m/s]") + ax3.set_ylabel("$Power [MW]$") + ax3.set_title("$Power$") + ax3.grid(True) + ax3.legend() + plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) + if __name__ == "__main__": main() \ No newline at end of file From 39afb33fb1be49206578c5bbbefc76ee98442cbc Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 10 Jul 2026 10:22:50 -0400 Subject: [PATCH 27/50] Working ROSCO functionality with parallelization for control table generation --- MITRotor/FlorisInterface/FlorisInterface.py | 29 +- MITRotor/FlorisInterface/ROSCOInterface.py | 543 ++++-- MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml | 2 +- examples/example_08_floris_rosco.py | 178 +- poetry.lock | 1620 +++++++++++------ pyproject.toml | 2 + 6 files changed, 1564 insertions(+), 810 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 102575f..c035bd7 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -2,7 +2,7 @@ import numpy as np import polars as pl from attrs import define, field -from typing import Optional +from typing import Optional, Callable, Union from scipy.interpolate import interp1d, RegularGridInterpolator # FLORIS Imports from floris.type_dec import floris_float_type, NDArrayFloat @@ -15,9 +15,11 @@ from MITRotor.Geometry import BEMGeometry from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM -from MITRotor.FlorisInterface.ROSCOInterface import query_controls +from MITRotor.FlorisInterface.ROSCOInterface import query_controls_compat from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw +InterpLike = Union[interp1d, RegularGridInterpolator, Callable] + # default rotor if none provided by user (IEA 15MW) def default_bem_factory(): return BEM( @@ -74,10 +76,10 @@ class MITRotorTurbine(BaseOperationModel): # TODO: figure out the default factory for the tsr and pitch!! Use saved file... # create interp objects based on pitch and tsr csvs # pitch_interp = field(init = True, factory = default_pitch_interp, type = interp1d, repr = False) - pitch_interp = field(init = True, default = None, type = RegularGridInterpolator, repr = False) + pitch_interp = field(init=True, default=None, type=Optional[InterpLike], repr=False) pitch_rad = field(init = True, default = True, type = bool) # tsr_interp = field(init = True, factory = default_tsr_interp, type = interp1d, repr = False) - tsr_interp = field(init = True, default = False, type = RegularGridInterpolator, repr = False) + tsr_interp = field(init=True, default=None, type=Optional[InterpLike], repr=False) rated_rotor_speed = field(init=True, default=None, type=Optional[float]) # [rad/s] # save most recent solution by unique floris arguments @@ -90,6 +92,10 @@ def __attrs_post_init__(self): if self.eff_ratio is None: gearbox_eff = self.bem_model.rotor.rosco_values[1] self.eff_ratio = (self.gen_eff / 100.0) * (gearbox_eff / 100.0) + if self.pitch_interp is None: + self.pitch_interp = default_pitch_interp() # 1D legacy default + if self.tsr_interp is None: + self.tsr_interp = default_tsr_interp() # 1D legacy default def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_angles: np.ndarray) -> tuple: # saves key to uniquely identify farm state -> avoids re-solving for calls to power, thrust, and induction for same state @@ -129,8 +135,15 @@ def _update_solution(self, # get setpoints yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) eff_yaw = calc_eff_yaw(yaw, tilt) - pitch = query_controls(self.pitch_interp, rotor_average_velocities, eff_yaw) - tsr = query_controls(self.tsr_interp, rotor_average_velocities, eff_yaw) + # pitch = query_controls(self.pitch_interp, rotor_average_velocities, eff_yaw) + # tsr = query_controls(self.tsr_interp, rotor_average_velocities, eff_yaw) + pitch = query_controls_compat( + self.pitch_interp, rotor_average_velocities, eff_yaw, kind = "pitch" + ) + tsr = query_controls_compat( + self.tsr_interp, rotor_average_velocities, eff_yaw, kind = "tsr", + rated_rotor_speed = self.rated_rotor_speed, rotor_radius = self.bem_model.rotor.R, + ) # pitch = self.pitch_interp(rotor_normal_average_velocities) if not self.pitch_rad: pitch = np.deg2rad(pitch) @@ -169,4 +182,6 @@ def thrust_coefficient(self, **kwargs) -> NDArrayFloat: def axial_induction(self, **kwargs) -> NDArrayFloat: self._update_solution(**kwargs) - return self._a \ No newline at end of file + return self._a + + # near_wake_velocities \ No newline at end of file diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 5ed046e..de391fa 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -7,6 +7,13 @@ from pathlib import Path from scipy.interpolate import interp1d, RegularGridInterpolator import warnings +import sys +from contextlib import contextmanager +# Parallelization modules +from types import SimpleNamespace +from joblib import Parallel, delayed +from tqdm.auto import tqdm +from tqdm_joblib import tqdm_joblib # ROSCO toolbox modules from rosco import discon_lib_path as lib_name from rosco.toolbox import controller as ROSCO_controller @@ -105,40 +112,253 @@ def load_from_mitrotor( # ----------------------------- # Generate control scheme # ----------------------------- +def _run_one_wind_row( + i, v, yaw_grid_rad, init_pitch_deg0, init_tsr0, + turbine_sim, bem, param_filename, dt, SimName +): + """ + Worker: solve all yaw points for a single wind speed index i. + Uses sequential warm-start across yaw in this row. + Returns row arrays (pitch/tsr/power), with NaN on fail/non-convergence. + """ + ny = len(yaw_grid_rad) + pitch_row = np.full(ny, np.nan, dtype=float) + tsr_row = np.full(ny, np.nan, dtype=float) + power_row = np.full(ny, np.nan, dtype=float) + + # Warm-start seeds for first yaw in this wind row + prev_pitch_deg = float(init_pitch_deg0) + prev_tsr = float(init_tsr0) + + for j, yaw_rad in enumerate(yaw_grid_rad): + controller_int = None + try: + init_omega = prev_tsr * v / turbine_sim.rotor_radius + init_gen = init_omega * turbine_sim.Ng + + controller_int = WarmStartControllerInterface( + lib_name, + param_filename=param_filename, + sim_name=f"{SimName}_{i}_{j}", + DT=dt, + init_ws=v, + init_rot_speed=init_omega, + init_gen_speed=init_gen, + init_pitch_deg=prev_pitch_deg, # deg + init_torque=0.0, + init_nac_imu=yaw_rad, # rad + ) + + # lightweight sim object compatible with sim_ws_mitrotor + sim = SimpleNamespace(turbine=turbine_sim, controller_int=controller_int) + + converged = sim_ws_mitrotor( + sim=sim, bem=bem, ws=v, dt=dt, + init_tsr=prev_tsr, + init_pitch=prev_pitch_deg, # deg + yaw_init=yaw_rad, # rad + wd=0.0, + verbose=False, + ) + + # Save only converged points; else remain NaN + if converged: + pitch_row[j] = sim.bld_pitch # rad + tsr_row[j] = sim.tsr + power_row[j] = sim.gen_power + + # update warm-start for next yaw + prev_pitch_deg = np.rad2deg(sim.bld_pitch) + prev_tsr = sim.tsr + + except Exception: + # leave NaN and continue to next yaw + if controller_int is not None: + try: + controller_int.kill_discon() + except Exception: + pass + continue + + return i, pitch_row, tsr_row, power_row + + +# def get_rosco_control_interps( +# rosco_yaml, bem, +# TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', SimName = "Sim1", +# GenEff = 95.756, generator_inertia = 1836784, +# regenerate = False, +# save_control_file = None, +# save_dir = ".", +# dt = 0.05, +# yaw_grid_deg = np.arange(0.0, 25.0, 1.0), # in degrees +# ): +# """ +# Creates pitch and tsr 2D interpolators using ROSCO controller tuning. + +# Creates turbine and controller. Controller is tuned on yaw = 0 Cp/Ct surfaces from MITRotor. +# ROSCO simulation with controller and turbrine is then run for each (wind_speed, yaw) combination +# till steady state. Steady-state set points are made into a 2D interpolator and optionally saved to +# a CSV. + +# Args: +# rosco_yaml (string): yaml file (+path) that defineds turbine and control parameters; +# [see MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml for example] +# bem (MITRotor.BEM): MITRotor BEM object +# TurbineName (string): string turbine name; default to "IEA15MW" +# GenEff (float): generator efficiency (0-100); defaults to IEA15MW value 95.756 +# generator_inertia (float): generator_inertia; defaults to IEA15MW value 1836784 [kg m^2] +# save_control_file (string): file name (+path) of saved look-up table value; if None (default) then not saved +# regenerate (bool): if True, then regenerate control path, else use saved in save_control_file; if save_control_file is None, set to True +# save_dir (string): path to save all files output when creating the interpolaters +# dt (float): timestep for ROSCO simulation; default = 0.05 seconds + +# Returns: +# pitch_interp (string): 1D pitch interpolator from wind speed tuned with ROSCO control paramters +# tsr_interp (string): 1D tsr interpolator from wind speed tuned with ROSCO control paramters +# rated_rotor_speed (float): rated rotor speed value +# """ + +# # load ROSCO inputs and make basic turbine +# inps = load_rosco_yaml(rosco_yaml) +# turbine_params = inps['turbine_params'] +# turbine = ROSCO_turbine.Turbine(turbine_params) + +# # if control csv exists and do not want to regenerate, load old csv +# if not regenerate and save_control_file is not None: +# pitch_interp, tsr_interp = load_control_interps_from_csv(save_control_file) +# return pitch_interp, tsr_interp, turbine.rated_rotor_speed + +# # load and check control parameters +# controller_params = inps['controller_params'] +# if controller_params["WE_Mode"] != 0: +# warnings.warn( +# "Using wind speed estimators in this simple simulation is known to cause problems. We suggest using WE_Mode = 0.", +# UserWarning, +# ) + +# # generate turbine Cp/Ct surfaces +# turbine = load_from_mitrotor( +# turbine, bem, +# TurbineName = TurbineName, rotor_performance_filename = rotor_performance_filename, +# generator_inertia = generator_inertia, GenEff = GenEff, +# yaw = 0.0, +# ) +# # save turbine Cp/Ct surface +# cp_filename = turbine.rotor_performance_filename +# write_rotor_performance(turbine, txt_filename=cp_filename) + +# # make and tune controller +# controller = ROSCO_controller.Controller(controller_params) +# controller.tune_controller(turbine) + +# # Write parameter input file +# param_filename = os.path.join(save_dir,'DISCON.IN') +# write_DISCON( +# turbine,controller, +# param_file=param_filename, +# txt_filename=cp_filename +# ) + +# # load initial setpoints from tuned controller +# init_pitch_list = np.rad2deg(np.maximum(controller.pitch_op, controller.ps_min_bld_pitch)) +# init_tsr_list = controller.TSR_op + +# # load/set values for interpolator axes +# v_grid = controller.v.copy() +# yaw_grid_deg = np.asarray(yaw_grid_deg, dtype=float) +# yaw_grid_rad = np.deg2rad(yaw_grid_deg) + +# pitch_tbl = np.zeros((len(v_grid), len(yaw_grid_rad))) +# tsr_tbl = np.zeros_like(pitch_tbl) +# power_tbl = np.zeros_like(pitch_tbl) + +# # needed constants +# R = turbine.rotor_radius +# GBRatio = turbine.Ng + +# # loop through interpolator axes and find setpoints using ROSCO simulation +# for (i, v) in enumerate(v_grid): +# # initial guess setpoints based on tuned controller +# init_pitch = init_pitch_list[i] +# init_tsr = init_tsr_list[i] +# init_omega = init_tsr * v / R +# init_gen = init_omega * GBRatio +# # loop through yaw +# for (j, yaw_rad) in enumerate(yaw_grid_rad): +# # create controller interface +# controller_int = WarmStartControllerInterface( +# lib_name, +# param_filename=param_filename, +# sim_name=f"{SimName}_{i}_{j}", +# DT=dt, +# init_ws=v, +# init_rot_speed=init_omega, +# init_gen_speed=init_gen, +# init_pitch_deg=init_pitch, # init_pitch is in deg +# init_torque=0.0, +# init_nac_imu=yaw_rad, # init_nac_imu is rad +# ) + +# # create the ROSCO simulation +# sim = ROSCO_sim.Sim(turbine, controller_int) +# # run the simulation to steady state +# sim_ws_mitrotor( +# sim=sim, bem=bem, ws=v, dt=dt, +# init_tsr=init_tsr, +# init_pitch=init_pitch, # deg +# yaw_init=yaw_rad, # rad +# wd=0.0, +# ) +# # save setpoints in 2D tables +# pitch_tbl[i, j] = sim.bld_pitch +# tsr_tbl[i, j] = sim.tsr +# power_tbl[i, j] = sim.gen_power + +# # save CSV of (optional) +# if save_control_file is not None: +# save_control_file = Path(save_control_file) +# save_control_file.parent.mkdir(parents=True, exist_ok=True) + +# vv, yy = np.meshgrid(v_grid, yaw_grid_rad, indexing="ij") +# data = np.column_stack([ +# vv.ravel(), # wind_speed_mps +# yy.ravel(), # yaw_rad +# pitch_tbl.ravel(), # pitch_rad +# tsr_tbl.ravel(), # tsr +# power_tbl.ravel(), # generated power +# ]) + +# header = "wind_speed_mps,yaw_rad,pitch_rad,tsr,gen_power" +# np.savetxt(save_control_file, data, delimiter=",", header=header, comments="") + +# # Direct 2D interpolators, no custom wrapper +# pitch_interp = RegularGridInterpolator( +# (v_grid, yaw_grid_rad), pitch_tbl, +# method="linear", bounds_error=False, fill_value=None +# ) +# tsr_interp = RegularGridInterpolator( +# (v_grid, yaw_grid_rad), tsr_tbl, +# method="linear", bounds_error=False, fill_value=None +# ) + +# return pitch_interp, tsr_interp, turbine.rated_rotor_speed + def get_rosco_control_interps( rosco_yaml, bem, - TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', SimName = "Sim1", - GenEff = 95.756, generator_inertia = 1836784, - regenerate = False, - save_control_file = None, - save_dir = ".", - dt = 0.05, - yaw_grid_deg = np.arange(0.0, 25.0, 1.0), # in degrees + TurbineName="IEA15MW", rotor_performance_filename='Cp_Ct_Cq.txt', SimName="Sim1", + GenEff=95.756, generator_inertia=1836784, + regenerate=False, + save_control_file=None, + save_dir=".", + dt=0.05, + yaw_grid_deg=np.arange(0.0, 25.0, 1.0), # degrees + n_jobs=-1, # parallel workers across wind speeds ): """ Creates pitch and tsr 2D interpolators using ROSCO controller tuning. - - Creates turbine and controller. Controller is tuned on yaw = 0 Cp/Ct surfaces from MITRotor. - ROSCO simulation with controller and turbrine is then run for each (wind_speed, yaw) combination - till steady state. Steady-state set points are made into a 2D interpolator and optionally saved to - a CSV. - - Args: - rosco_yaml (string): yaml file (+path) that defineds turbine and control parameters; - [see MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml for example] - bem (MITRotor.BEM): MITRotor BEM object - TurbineName (string): string turbine name; default to "IEA15MW" - GenEff (float): generator efficiency (0-100); defaults to IEA15MW value 95.756 - generator_inertia (float): generator_inertia; defaults to IEA15MW value 1836784 [kg m^2] - save_control_file (string): file name (+path) of saved look-up table value; if None (default) then not saved - regenerate (bool): if True, then regenerate control path, else use saved in save_control_file; if save_control_file is None, set to True - save_dir (string): path to save all files output when creating the interpolaters - dt (float): timestep for ROSCO simulation; default = 0.05 seconds - - Returns: - pitch_interp (string): 1D pitch interpolator from wind speed tuned with ROSCO control paramters - tsr_interp (string): 1D tsr interpolator from wind speed tuned with ROSCO control paramters - rated_rotor_speed (float): rated rotor speed value + Parallelized over wind speeds; yaws for each wind are solved sequentially + in one worker with warm-start chaining. """ # load ROSCO inputs and make basic turbine @@ -155,17 +375,19 @@ def get_rosco_control_interps( controller_params = inps['controller_params'] if controller_params["WE_Mode"] != 0: warnings.warn( - "Using wind speed estimators in this simple simulation is known to cause problems. We suggest using WE_Mode = 0.", + "Using wind speed estimators in this simple simulation is known to cause problems. " + "We suggest using WE_Mode = 0.", UserWarning, ) # generate turbine Cp/Ct surfaces turbine = load_from_mitrotor( turbine, bem, - TurbineName = TurbineName, rotor_performance_filename = rotor_performance_filename, - generator_inertia = generator_inertia, GenEff = GenEff, - yaw = 0.0, + TurbineName=TurbineName, rotor_performance_filename=rotor_performance_filename, + generator_inertia=generator_inertia, GenEff=GenEff, + yaw=0.0, ) + # save turbine Cp/Ct surface cp_filename = turbine.rotor_performance_filename write_rotor_performance(turbine, txt_filename=cp_filename) @@ -175,86 +397,113 @@ def get_rosco_control_interps( controller.tune_controller(turbine) # Write parameter input file - param_filename = os.path.join(save_dir,'DISCON.IN') + param_filename = os.path.join(save_dir, 'DISCON.IN') write_DISCON( - turbine,controller, - param_file=param_filename, + turbine, controller, + param_file=param_filename, txt_filename=cp_filename ) - # load initial setpoints from tuned controller + # tuned initial setpoints init_pitch_list = np.rad2deg(np.maximum(controller.pitch_op, controller.ps_min_bld_pitch)) init_tsr_list = controller.TSR_op - # load/set values for interpolator axes + # axes v_grid = controller.v.copy() - yaw_grid_deg = np.asarray(yaw_grid_deg, dtype=float) + yaw_grid_deg = np.sort(np.asarray(yaw_grid_deg, dtype=float)) yaw_grid_rad = np.deg2rad(yaw_grid_deg) - pitch_tbl = np.zeros((len(v_grid), len(yaw_grid_rad))) - tsr_tbl = np.zeros_like(pitch_tbl) - power_tbl = np.zeros_like(pitch_tbl) + pitch_tbl = np.full((len(v_grid), len(yaw_grid_rad)), np.nan, dtype=float) + tsr_tbl = np.full_like(pitch_tbl, np.nan) + power_tbl = np.full_like(pitch_tbl, np.nan) + + # lightweight turbine object for worker pickling + turbine_sim = SimpleNamespace( + rotor_radius=float(turbine.rotor_radius), + rho=float(turbine.rho), + Ng=float(turbine.Ng), + J=float(turbine.J), + GBoxEff=float(turbine.GBoxEff), + GenEff=float(turbine.GenEff), + ) - # needed constants - R = turbine.rotor_radius - GBRatio = turbine.Ng - - # loop through interpolator axes and find setpoints using ROSCO simulation - for (i, v) in enumerate(v_grid): - # initial guess setpoints based on tuned controller - init_pitch = init_pitch_list[i] - init_tsr = init_tsr_list[i] - init_omega = init_tsr * v / R - init_gen = init_omega * GBRatio - # loop through yaw - for (j, yaw_rad) in enumerate(yaw_grid_rad): - # create controller interface - controller_int = WarmStartControllerInterface( - lib_name, - param_filename=param_filename, - sim_name=f"{SimName}_{i}_{j}", - DT=dt, - init_ws=v, - init_rot_speed=init_omega, - init_gen_speed=init_gen, - init_pitch_deg=init_pitch, # init_pitch is in deg - init_torque=0.0, - init_nac_imu=yaw_rad, # init_nac_imu is rad - ) + n_wind = len(v_grid) + n_yaw = len(yaw_grid_rad) + total_cases = n_wind * n_yaw - # create the ROSCO simulation - sim = ROSCO_sim.Sim(turbine, controller_int) - # run the simulation to steady state - sim_ws_mitrotor( - sim=sim, bem=bem, ws=v, dt=dt, - init_tsr=init_tsr, - init_pitch=init_pitch, # deg - yaw_init=yaw_rad, # rad - wd=0.0, - ) - # save setpoints in 2D tables - pitch_tbl[i, j] = sim.bld_pitch - tsr_tbl[i, j] = sim.tsr - power_tbl[i, j] = sim.gen_power + # determine effective n_jobs + if n_jobs is None: + n_jobs_eff = 1 + elif n_jobs == -1: + n_jobs_eff = min(os.cpu_count() or 1, n_wind) + else: + n_jobs_eff = max(1, min(int(n_jobs), n_wind)) + + # run parallel (fallback to serial on failure, e.g., pickling issue) + print( + f"Starting control LUT sweep: {n_wind} wind-row tasks " + f"({total_cases} wind-yaw cases), using {n_jobs_eff} worker process(es)." + ) - # save CSV of (optional) + def _run_serial(desc): + out = [] + for i, v in enumerate(tqdm(v_grid, total=n_wind, desc=desc, dynamic_ncols=True)): + out.append( + _run_one_wind_row( + i, v, yaw_grid_rad, init_pitch_list[i], init_tsr_list[i], + turbine_sim, bem, param_filename, dt, SimName + ) + ) + return out + + rows = None + if n_jobs_eff > 1: + bar = tqdm(total=n_wind, desc="Control LUT sweep (wind rows)", dynamic_ncols=True) + try: + with tqdm_joblib(bar): + rows = Parallel(n_jobs=n_jobs_eff, backend="loky", verbose=0, batch_size=1)( + delayed(_run_one_wind_row)( + i, v, yaw_grid_rad, init_pitch_list[i], init_tsr_list[i], + turbine_sim, bem, param_filename, dt, SimName + ) + for i, v in enumerate(v_grid) + ) + except Exception as e: + warnings.warn( + f"Parallel execution failed ({type(e).__name__}: {e}). " + "Falling back to serial execution.", + RuntimeWarning, + ) + finally: + bar.close() + if rows is None: + desc = "Control LUT sweep (serial fallback)" if n_jobs_eff > 1 else "Control LUT sweep (serial)" + rows = _run_serial(desc) + + # collect + for i, pitch_row, tsr_row, power_row in rows: + pitch_tbl[i, :] = pitch_row + tsr_tbl[i, :] = tsr_row + power_tbl[i, :] = power_row + + # optional CSV save if save_control_file is not None: save_control_file = Path(save_control_file) save_control_file.parent.mkdir(parents=True, exist_ok=True) vv, yy = np.meshgrid(v_grid, yaw_grid_rad, indexing="ij") data = np.column_stack([ - vv.ravel(), # wind_speed_mps - yy.ravel(), # yaw_rad - pitch_tbl.ravel(), # pitch_rad - tsr_tbl.ravel(), # tsr - power_tbl.ravel(), # generated power + vv.ravel(), # wind_speed_mps + yy.ravel(), # yaw_rad + pitch_tbl.ravel(), # pitch_rad + tsr_tbl.ravel(), # tsr + power_tbl.ravel(), # generated power ]) header = "wind_speed_mps,yaw_rad,pitch_rad,tsr,gen_power" np.savetxt(save_control_file, data, delimiter=",", header=header, comments="") - # Direct 2D interpolators, no custom wrapper + # interpolators pitch_interp = RegularGridInterpolator( (v_grid, yaw_grid_rad), pitch_tbl, method="linear", bounds_error=False, fill_value=None @@ -302,34 +551,78 @@ def load_control_interps_from_csv(csv_path): return pitch_interp, tsr_interp -# def query_control(pitch_interp, tsr_interp, ws, yaw_rad): -# pitch = query_pitch(pitch_interp, ws, yaw_rad) -# tsr = query_tsr(tsr_interp, ws, yaw_rad) -# return pitch, tsr -def query_controls(interp, ws, yaw_rad): - """ - Vectorized query for 2D interpolator interp(ws, yaw). +# def query_controls(interp, ws, yaw_rad): +# """ +# Vectorized query for 2D interpolator interp(ws, yaw). + +# Supports: +# - scalar ws, scalar yaw -> float +# - array ws, scalar yaw -> array +# - scalar ws, array yaw -> array +# - array ws, array yaw (broadcastable shapes, including same-length 1D pairwise) -> array +# """ +# ws_arr = np.asarray(ws, dtype=float) +# yaw_arr = np.asarray(yaw_rad, dtype=float) + +# # Broadcast to common shape (or raise if incompatible) +# ws_b, yaw_b = np.broadcast_arrays(ws_arr, yaw_arr) + +# # Build points for RegularGridInterpolator: shape (N, 2) +# pts = np.column_stack((ws_b.ravel(), yaw_b.ravel())) + +# # Vectorized interpolation +# vals = np.asarray(interp(pts)).reshape(ws_b.shape) +# # Return float for scalar input, ndarray otherwise +# return float(vals) if vals.shape == () else vals + +def query_controls_compat( + interp, + ws, + yaw_rad, + *, + kind="generic", # "pitch" or "tsr" + rated_rotor_speed=None, # rad/s (for 1D tsr scheme) + rotor_radius=None, # m (required if rated_rotor_speed is set) +): + """ Supports: - - scalar ws, scalar yaw -> float - - array ws, scalar yaw -> array - - scalar ws, array yaw -> array - - array ws, array yaw (broadcastable shapes, including same-length 1D pairwise) -> array + - 2D RegularGridInterpolator: interp(ws, yaw) + - 1D interp1d/callable: interp(ws), yaw ignored (warn if |yaw| > 0) + + For 1D TSR and rated_rotor_speed provided: + applies simple above-rated cap via omega = tsr*ws/R. """ ws_arr = np.asarray(ws, dtype=float) yaw_arr = np.asarray(yaw_rad, dtype=float) - - # Broadcast to common shape (or raise if incompatible) ws_b, yaw_b = np.broadcast_arrays(ws_arr, yaw_arr) - # Build points for RegularGridInterpolator: shape (N, 2) - pts = np.column_stack((ws_b.ravel(), yaw_b.ravel())) + # 2D LUT path + if isinstance(interp, RegularGridInterpolator) and len(interp.grid) == 2: + pts = np.column_stack((ws_b.ravel(), yaw_b.ravel())) + vals = np.asarray(interp(pts)).reshape(ws_b.shape) + return float(vals) if vals.shape == () else vals + + # 1D legacy path + if np.any(np.abs(yaw_b) > 0): + warnings.warn( + "Using 1D control curve with nonzero yaw/tilt; yaw/tilt is ignored for lookup.", + UserWarning, + ) + + vals = np.asarray(interp(ws_b)).reshape(ws_b.shape) - # Vectorized interpolation - vals = np.asarray(interp(pts)).reshape(ws_b.shape) + if kind == "tsr": + if rated_rotor_speed is not None: + if rotor_radius is None: + raise ValueError("rotor_radius is required when rated_rotor_speed is set.") + omega_lookup = vals * ws_b / np.maximum(rotor_radius, 1e-12) + tsr_from_rated = rated_rotor_speed * rotor_radius / np.maximum(ws_b, 1e-6) + vals = np.where(omega_lookup <= rated_rotor_speed, vals, tsr_from_rated) + + vals = np.maximum(vals, 0.0) - # Return float for scalar input, ndarray otherwise return float(vals) if vals.shape == () else vals @@ -364,8 +657,8 @@ def sim_ws_mitrotor( gen_speed = rot_speed * Ng # rad/s gen_torque = 0.0 # Nm gen_power = 0.0 # W - nac_yaw = yaw_init # rad - nac_yawrate = 0.0 # rad/s + nac_yaw = yaw_init # deg + nac_yawrate = 0.0 # deg/s # Convergence tracker tracker = init_convergence_tracker(dt, conv_settings) @@ -587,11 +880,41 @@ def init_discon(self): self.avrSWAP[50] = len(self.avcOUTNAME) self.avrSWAP[51] = self.char_buffer - self.call_discon() # iStatus=0 init call + with suppress_c_output(): + self.call_discon() # iStatus=0 init call + self.avrSWAP[0] = 1 # subsequent calls are normal if self.aviFAIL.value < 0: raise ValueError("ROSCO dynamic library has returned an error") + def kill_discon(self): + """Silent DISCON shutdown (suppresses ROSCO shutdown print spam).""" + try: + with suppress_c_output(): # the context manager you already added + super().kill_discon() + except Exception: + pass + + +@contextmanager +def suppress_c_output(): + """Suppress C/Fortran prints (stdout/stderr) in this process.""" + sys.stdout.flush() + sys.stderr.flush() + + devnull = os.open(os.devnull, os.O_WRONLY) + old_stdout = os.dup(1) + old_stderr = os.dup(2) + try: + os.dup2(devnull, 1) + os.dup2(devnull, 2) + yield + finally: + os.dup2(old_stdout, 1) + os.dup2(old_stderr, 2) + os.close(old_stdout) + os.close(old_stderr) + os.close(devnull) # ----------------------------- diff --git a/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml index 85a5d3a..15f0975 100644 --- a/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml +++ b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml @@ -27,7 +27,7 @@ turbine_params: #------------------------------- CONTROLLER PARAMETERS ---------------------------------- controller_params: # Controller flags - LoggingLevel: 2 # {0: write no debug files, 1: write standard output .dbg-file, 2: write standard output .dbg-file and complete avrSWAP-array .dbg2-file + LoggingLevel: 0 # {0: write no debug files, 1: write standard output .dbg-file, 2: write standard output .dbg-file and complete avrSWAP-array .dbg2-file F_LPFType: 2 # {1: first-order low-pass filter, 2: second-order low-pass filter}, [rad/s] (currently filters generator speed and pitch control signals) F_NotchType: 0 # Notch on the measured generator speed {0: disable, 1: enable} IPC_ControlMode: 0 # Turn Individual Pitch Control (IPC) for fatigue load reductions (pitch contribution) {0: off, 1: 1P reductions, 2: 1P+2P reductions} diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 99d2d38..30035fb 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -22,11 +22,11 @@ from MITRotor.Momentum import UnifiedMomentumLUT from MITRotor import BEM, BEMGeometry, IEA15MW from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp -from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls +from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls_compat figdir = Path("fig") -def change_control_param(param_key, param_value, template_yaml, bem): +def change_control_param(param_key, param_value, template_yaml, bem, regenerate = False, save_control_file = "control.csv"): yaml = YAML() with tempfile.TemporaryDirectory() as tmpdir: temp_yaml = Path(tmpdir) / "rosco_temp.yaml" @@ -39,7 +39,10 @@ def change_control_param(param_key, param_value, template_yaml, bem): with open(temp_yaml, "w") as f: yaml.dump(data, f) - pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps(temp_yaml, bem) + pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( + temp_yaml, bem, + regenerate = regenerate, save_control_file = save_control_file, + ) return pitch_interp, tsr_interp, rated_rotor_speed def get_turbine_power_coefficent(fturbine, fmodel, wind_speeds): @@ -87,26 +90,30 @@ def main(): rosco_yaml_PS_Mode_3 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp, rosco_PS_Mode_3_rated_rotorspeed = get_rosco_control_interps( rosco_yaml_PS_Mode_3, bem, - regenerate = False, save_control_file = "control.csv") + # regenerate = False, save_control_file = "control.csv") + regenerate = True, save_control_file = "control.csv") end = time.time() print(f"Time to make control CSV: {end - start}") - # rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param("PS_Mode", 0, rosco_yaml_PS_Mode_3, bem) + rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param( + "PS_Mode", 0, rosco_yaml_PS_Mode_3, bem, + regenerate = True, save_control_file = "control_PS0.csv" + ) # Plot IEA15MW control from ROSCO paper, ROSOC control with PS_Mode = 3, and ROSOC control with PS_Mode = 0 pitch_abbas = abbas_pitch_interp(wind_speeds) - # pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) - pitch_ps3 = np.rad2deg(query_controls(rosco_PS_Mode_3_pitch_interp, wind_speeds, 0.0)) + pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) + pitch_ps3 = np.rad2deg(query_controls_compat(rosco_PS_Mode_3_pitch_interp, wind_speeds, 0.0)) tsr_abbas = abbas_tsr_interp(wind_speeds) - # tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) - tsr_ps3 = query_controls(rosco_PS_Mode_3_tsr_interp, wind_speeds, 0.0) + tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) + tsr_ps3 = query_controls_compat(rosco_PS_Mode_3_tsr_interp, wind_speeds, 0.0) # Create figure fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) fig.suptitle(fr"Setpoint Trajectories") # Plot pitch - # ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) + ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") @@ -116,7 +123,7 @@ def main(): ax[0].grid(True) # Plot TSR - # ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) + ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") @@ -129,24 +136,24 @@ def main(): plt.savefig(figdir / "example_8_IEA15mw_controls.png", dpi=300) # make FLORIS turbines - # floris_default_turbine = MITRotorTurbine( - # bem_model = bem, - # ) - - # floris_abbas_turbine = MITRotorTurbine( - # bem_model = bem, - # pitch_interp = abbas_pitch_interp, - # pitch_rad = False, - # tsr_interp = abbas_tsr_interp, - # ) - - # floris_PS_Mode_0_turbine = MITRotorTurbine( - # bem_model = bem, - # pitch_interp = rosco_PS_Mode_0_pitch_interp, - # pitch_rad = True, - # tsr_interp = rosco_PS_Mode_0_tsr_interp, - # rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, - # ) + floris_default_turbine = MITRotorTurbine( + bem_model = bem, + ) + + floris_abbas_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = abbas_pitch_interp, + pitch_rad = False, + tsr_interp = abbas_tsr_interp, + ) + + floris_PS_Mode_0_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = rosco_PS_Mode_0_pitch_interp, + pitch_rad = True, + tsr_interp = rosco_PS_Mode_0_tsr_interp, + rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, + ) floris_PS_Mode_3_turbine = MITRotorTurbine( bem_model = bem, @@ -157,27 +164,26 @@ def main(): ) yaw = 0.0 # degrees yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] - # fmodel_default = FlorisModel("defaults") - # fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - # fmodel_default.set_operation_model(floris_default_turbine) - # fmodel_default.run() - # Ct_default = fmodel_default.get_turbine_thrust_coefficients() - # Cp_default, P_default = get_turbine_power_coefficent(floris_default_turbine, fmodel_default, wind_speeds) - - # fmodel_abbas = FlorisModel("defaults") - # fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - # fmodel_abbas.set_operation_model(floris_abbas_turbine) - # fmodel_abbas.run() - # Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() - # Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) - - - # fmodel_PS_Mode_0 = FlorisModel("defaults") - # fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - # fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) - # fmodel_PS_Mode_0.run() - # Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() - # Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) + fmodel_default = FlorisModel("defaults") + fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_default.set_operation_model(floris_default_turbine) + fmodel_default.run() + Ct_default = fmodel_default.get_turbine_thrust_coefficients() + Cp_default, P_default = get_turbine_power_coefficent(floris_default_turbine, fmodel_default, wind_speeds) + + fmodel_abbas = FlorisModel("defaults") + fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_abbas.set_operation_model(floris_abbas_turbine) + fmodel_abbas.run() + Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() + Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) + + fmodel_PS_Mode_0 = FlorisModel("defaults") + fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) + fmodel_PS_Mode_0.run() + Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() + Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) fmodel_PS_Mode_3 = FlorisModel("defaults") fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) @@ -189,18 +195,18 @@ def main(): # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (16,4), constrained_layout=True) fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = {yaw} for Different Control Strategies") - # ax1.plot( - # wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax1.plot( - # wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax1.plot( - # wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", - # lw=3, linestyle = "dashed", zorder = 1, - # ) + ax1.plot( + wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax1.plot( + wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax1.plot( + wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, + ) ax1.plot(wind_speeds, Ct_PS_Mode_3, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -210,18 +216,18 @@ def main(): ax1.grid(True) ax1.legend() - # ax2.plot( - # wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax2.plot( - # wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax2.plot( - # wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - # lw=3, linestyle = "dashed", zorder = 1, - # ) + ax2.plot( + wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", + lw=3, linestyle = "solid", zorder = 1, + ) + ax2.plot( + wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax2.plot( + wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, + ) ax2.plot(wind_speeds, Cp_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -231,18 +237,18 @@ def main(): ax2.grid(True) ax2.legend() - # ax3.plot( - # wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax3.plot( - # wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", - # lw=3, linestyle = "solid", zorder = 1, - # ) - # ax3.plot( - # # wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - # # lw=3, linestyle = "dashed", zorder = 1, - # # ) + ax3.plot( + wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot( + wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot( + wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, + ) ax3.plot(wind_speeds, P_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) diff --git a/poetry.lock b/poetry.lock index 9e62a5e..13fd70c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "anyio" -version = "4.13.0" +version = "4.14.1" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, - {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, + {file = "anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72"}, + {file = "anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e"}, ] [package.dependencies] @@ -170,14 +170,14 @@ dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)" [[package]] name = "beautifulsoup4" -version = "4.14.3" +version = "4.15.0" description = "Screen-scraping library" optional = false python-versions = ">=3.7.0" groups = ["dev"] files = [ - {file = "beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb"}, - {file = "beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86"}, + {file = "beautifulsoup4-4.15.0-py3-none-any.whl", hash = "sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9"}, + {file = "beautifulsoup4-4.15.0.tar.gz", hash = "sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7"}, ] [package.dependencies] @@ -242,22 +242,22 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bleach" -version = "6.3.0" +version = "6.4.0" description = "An easy safelist-based HTML-sanitizing tool." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6"}, - {file = "bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22"}, + {file = "bleach-6.4.0-py3-none-any.whl", hash = "sha256:4b6b6a54fff2e69a3dde9d21cc6301220bee3c3cb792187d11403fd795031081"}, + {file = "bleach-6.4.0.tar.gz", hash = "sha256:4202482733d85cedd04e59fcb2f89f4e4c7c385a78d3c3c23c30446843a37452"}, ] [package.dependencies] -tinycss2 = {version = ">=1.1.0,<1.5", optional = true, markers = "extra == \"css\""} +tinycss2 = {version = ">=1.1.0", optional = true, markers = "extra == \"css\""} webencodings = "*" [package.extras] -css = ["tinycss2 (>=1.1.0,<1.5)"] +css = ["tinycss2 (>=1.1.0)"] [[package]] name = "cachebox" @@ -383,108 +383,124 @@ files = [ [[package]] name = "certifi" -version = "2026.4.22" +version = "2026.6.17" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main", "dev"] files = [ - {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"}, - {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"}, + {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"}, + {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"}, ] [[package]] name = "cffi" -version = "2.0.0" +version = "2.1.0" description = "Foreign Function Interface for Python calling C code." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, - {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"}, - {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"}, - {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, - {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, - {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, - {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, - {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, - {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, - {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}, - {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}, - {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}, - {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}, - {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}, - {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}, - {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}, - {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}, - {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}, - {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"}, - {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"}, - {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, - {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, + {file = "cffi-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0"}, + {file = "cffi-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0"}, + {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43"}, + {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c"}, + {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd"}, + {file = "cffi-2.1.0-cp310-cp310-win32.whl", hash = "sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f"}, + {file = "cffi-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da"}, + {file = "cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc"}, + {file = "cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565"}, + {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c"}, + {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02"}, + {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e"}, + {file = "cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479"}, + {file = "cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458"}, + {file = "cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d"}, + {file = "cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f"}, + {file = "cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66"}, + {file = "cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe"}, + {file = "cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b"}, + {file = "cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a"}, + {file = "cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384"}, + {file = "cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6"}, + {file = "cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda"}, + {file = "cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b"}, + {file = "cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a"}, + {file = "cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224"}, + {file = "cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c"}, + {file = "cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a"}, + {file = "cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2"}, + {file = "cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512"}, + {file = "cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f"}, + {file = "cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a"}, + {file = "cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3"}, + {file = "cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d"}, + {file = "cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5"}, + {file = "cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce"}, + {file = "cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326"}, + {file = "cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd"}, + {file = "cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb"}, + {file = "cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804"}, + {file = "cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714"}, + {file = "cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056"}, + {file = "cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4"}, + {file = "cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94"}, + {file = "cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76"}, + {file = "cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5"}, + {file = "cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8"}, + {file = "cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c"}, + {file = "cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001"}, + {file = "cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3"}, + {file = "cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1"}, + {file = "cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28"}, + {file = "cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629"}, + {file = "cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6"}, + {file = "cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853"}, + {file = "cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda"}, + {file = "cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc"}, + {file = "cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f"}, + {file = "cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc"}, + {file = "cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9"}, + {file = "cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b"}, + {file = "cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5"}, + {file = "cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210"}, + {file = "cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9"}, ] markers = {main = "implementation_name == \"pypy\""} @@ -547,153 +563,117 @@ numpy = ">=1.21.2" [[package]] name = "charset-normalizer" -version = "3.4.7" +version = "3.4.9" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" groups = ["main", "dev"] files = [ - {file = "charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_armv7l.whl", hash = "sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win32.whl", hash = "sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win32.whl", hash = "sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c"}, - {file = "charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d"}, - {file = "charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-win32.whl", hash = "sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-win32.whl", hash = "sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-win32.whl", hash = "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:253a4a220747e8b5faf57ec320c4f5efb0cef05f647420bf267143ec15dba10a"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:68ce9f4d6b26d5ccbf7fd4459bf75f74a0a146677ebba80597df60cbdb20e6f4"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:58150c9f9b9a552505912d182ccdf26f6396fb6094816ceebcbb20eecabaed94"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df7276909358e5635ae203673ab7e509ddd224225a8d6b0790bf13eb2bde1cc5"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c09a49d6cde137258beb3d551994a2927fd35ad5cf96aed573f61bbd67c5f84"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:231ddcbb35e2ff8973e1365db41fe0572662893b99a05deb183b68ad4c0c8bd4"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:920079c3f7456fa213e0829ed2073aaa727fd39d889ead5b4f35d0de5460d04f"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0fa1aec2d32bcc03c8fa0f6f1712caad1adc38509f31142112e5c9daf5b9c833"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ad41ba96094304aa090f5a30cb6e4fb3b3f1c264c523394b4c39bbacc4dc92ba"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:43b9e366a31fdd1c87d0eb08f579b4a82b723ea54338f040d6b4e518a026ea29"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-win32.whl", hash = "sha256:93d59d504b230e83c7a843251681959a0b6a9cd76f6e146ce1b8a80eb8739af9"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-win_amd64.whl", hash = "sha256:ddf4af30b417d9fe16481e9b81c27ab2a7cde1ff7ba3e85653b02db7d145dc7b"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-win_arm64.whl", hash = "sha256:476743fe6dfe14a2da12e3ac79125dc84a3b2cf8094369a47a1529b0cd8549fe"}, + {file = "charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5"}, + {file = "charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b"}, ] [[package]] name = "click" -version = "8.4.0" +version = "8.4.2" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "click-8.4.0-py3-none-any.whl", hash = "sha256:40c50b7c6c6adac2823d411041ec84f3f103f1b280d5e9ce0d7f998995832f81"}, - {file = "click-8.4.0.tar.gz", hash = "sha256:638f1338fe1235c8f4e008e4a8a254fb5c5fbdcbb40ece3c9142ebb78e792973"}, + {file = "click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76"}, + {file = "click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6"}, ] [package.dependencies] @@ -956,42 +936,42 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "debugpy" -version = "1.8.20" +version = "1.8.21" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "debugpy-1.8.20-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:157e96ffb7f80b3ad36d808646198c90acb46fdcfd8bb1999838f0b6f2b59c64"}, - {file = "debugpy-1.8.20-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:c1178ae571aff42e61801a38b007af504ec8e05fde1c5c12e5a7efef21009642"}, - {file = "debugpy-1.8.20-cp310-cp310-win32.whl", hash = "sha256:c29dd9d656c0fbd77906a6e6a82ae4881514aa3294b94c903ff99303e789b4a2"}, - {file = "debugpy-1.8.20-cp310-cp310-win_amd64.whl", hash = "sha256:3ca85463f63b5dd0aa7aaa933d97cbc47c174896dcae8431695872969f981893"}, - {file = "debugpy-1.8.20-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:eada6042ad88fa1571b74bd5402ee8b86eded7a8f7b827849761700aff171f1b"}, - {file = "debugpy-1.8.20-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:7de0b7dfeedc504421032afba845ae2a7bcc32ddfb07dae2c3ca5442f821c344"}, - {file = "debugpy-1.8.20-cp311-cp311-win32.whl", hash = "sha256:773e839380cf459caf73cc533ea45ec2737a5cc184cf1b3b796cd4fd98504fec"}, - {file = "debugpy-1.8.20-cp311-cp311-win_amd64.whl", hash = "sha256:1f7650546e0eded1902d0f6af28f787fa1f1dbdbc97ddabaf1cd963a405930cb"}, - {file = "debugpy-1.8.20-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:4ae3135e2089905a916909ef31922b2d733d756f66d87345b3e5e52b7a55f13d"}, - {file = "debugpy-1.8.20-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:88f47850a4284b88bd2bfee1f26132147d5d504e4e86c22485dfa44b97e19b4b"}, - {file = "debugpy-1.8.20-cp312-cp312-win32.whl", hash = "sha256:4057ac68f892064e5f98209ab582abfee3b543fb55d2e87610ddc133a954d390"}, - {file = "debugpy-1.8.20-cp312-cp312-win_amd64.whl", hash = "sha256:a1a8f851e7cf171330679ef6997e9c579ef6dd33c9098458bd9986a0f4ca52e3"}, - {file = "debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a"}, - {file = "debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf"}, - {file = "debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393"}, - {file = "debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7"}, - {file = "debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173"}, - {file = "debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad"}, - {file = "debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f"}, - {file = "debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be"}, - {file = "debugpy-1.8.20-cp38-cp38-macosx_15_0_x86_64.whl", hash = "sha256:b773eb026a043e4d9c76265742bc846f2f347da7e27edf7fe97716ea19d6bfc5"}, - {file = "debugpy-1.8.20-cp38-cp38-manylinux_2_34_x86_64.whl", hash = "sha256:20d6e64ea177ab6732bffd3ce8fc6fb8879c60484ce14c3b3fe183b1761459ca"}, - {file = "debugpy-1.8.20-cp38-cp38-win32.whl", hash = "sha256:0dfd9adb4b3c7005e9c33df430bcdd4e4ebba70be533e0066e3a34d210041b66"}, - {file = "debugpy-1.8.20-cp38-cp38-win_amd64.whl", hash = "sha256:60f89411a6c6afb89f18e72e9091c3dfbcfe3edc1066b2043a1f80a3bbb3e11f"}, - {file = "debugpy-1.8.20-cp39-cp39-macosx_15_0_x86_64.whl", hash = "sha256:bff8990f040dacb4c314864da95f7168c5a58a30a66e0eea0fb85e2586a92cd6"}, - {file = "debugpy-1.8.20-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:70ad9ae09b98ac307b82c16c151d27ee9d68ae007a2e7843ba621b5ce65333b5"}, - {file = "debugpy-1.8.20-cp39-cp39-win32.whl", hash = "sha256:9eeed9f953f9a23850c85d440bf51e3c56ed5d25f8560eeb29add815bd32f7ee"}, - {file = "debugpy-1.8.20-cp39-cp39-win_amd64.whl", hash = "sha256:760813b4fff517c75bfe7923033c107104e76acfef7bda011ffea8736e9a66f8"}, - {file = "debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7"}, - {file = "debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33"}, + {file = "debugpy-1.8.21-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:8eeab7b5462f683452c57c0126aaa5ec4e974ddb705f39ba87dff8818c8e08f9"}, + {file = "debugpy-1.8.21-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:0fddfdc130ac6d8bfc0415b0409822fa901c8f310e5c945ac5653a0352532344"}, + {file = "debugpy-1.8.21-cp310-cp310-win32.whl", hash = "sha256:72b5d676c4cbfac3bac5bb01c138a4656e843f93f03ce2a5f4e394ad49fbee73"}, + {file = "debugpy-1.8.21-cp310-cp310-win_amd64.whl", hash = "sha256:a7fe47fd23da57b9e0bec3f4a8ee65a2dc55782455ed7f2141d75ab5d2eaeef5"}, + {file = "debugpy-1.8.21-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:da456226c7b4c69e35dbe35dcee6623d912000a77816db7856a41af1c72a0264"}, + {file = "debugpy-1.8.21-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:f68b891688e61bdc08b8d364d919ff0051e0b94657b39dcd027bc3173edb7cdc"}, + {file = "debugpy-1.8.21-cp311-cp311-win32.whl", hash = "sha256:f843a8b08c2edeaf9b1582eed4f25441af21a297c22ff16bf76a662557aa9c9e"}, + {file = "debugpy-1.8.21-cp311-cp311-win_amd64.whl", hash = "sha256:84c564d8cc701d41843b29a92814c1f1bef6798724ca9d675c284ad9f6a547d7"}, + {file = "debugpy-1.8.21-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:9f96713896f39c3dff0ee841f47320c3f2983d33c341e009361bb0ebc79adc4e"}, + {file = "debugpy-1.8.21-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:c193d474f0a211191f2b4449d2d06157c689013035bd952f3b617e0ef422b176"}, + {file = "debugpy-1.8.21-cp312-cp312-win32.whl", hash = "sha256:4743373c1cac7f9e74a1b9915bf1dbe0e900eca657ffb170ae07ac8363205ae9"}, + {file = "debugpy-1.8.21-cp312-cp312-win_amd64.whl", hash = "sha256:bd7ba9dd3daa7c2f942c6ca8d4695a16bf9ac16b63615261c7982bc74f7ed20c"}, + {file = "debugpy-1.8.21-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:13678151fc401e2d68c9880b91e28714f797d40422994572b24560ef80910a88"}, + {file = "debugpy-1.8.21-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:ecbd158386c31ffe71d46f72d44d56e66331ab9b16cad649156d514368f23ab2"}, + {file = "debugpy-1.8.21-cp313-cp313-win32.whl", hash = "sha256:2c2ae706dec41d99a9ca1f7ebc987a83e65578363be6f6b3ac9067504917fae1"}, + {file = "debugpy-1.8.21-cp313-cp313-win_amd64.whl", hash = "sha256:aa648733047443eb1d07682c4ef287d36a54507b643ffdf38b09a3ef002c72a0"}, + {file = "debugpy-1.8.21-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782"}, + {file = "debugpy-1.8.21-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e"}, + {file = "debugpy-1.8.21-cp314-cp314-win32.whl", hash = "sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c"}, + {file = "debugpy-1.8.21-cp314-cp314-win_amd64.whl", hash = "sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8"}, + {file = "debugpy-1.8.21-cp38-cp38-macosx_15_0_x86_64.whl", hash = "sha256:0042da0ecd0a8b50dc4a54395ecd870d258d73fa18776f50c91fdcabdcad2675"}, + {file = "debugpy-1.8.21-cp38-cp38-manylinux_2_34_x86_64.whl", hash = "sha256:ffd932c6796afadab6993ec96745918a8cb2444dbd392074f769db5ea40ab440"}, + {file = "debugpy-1.8.21-cp38-cp38-win32.whl", hash = "sha256:4e7c2d784d78ad4b71a5f8cd7b59c167719ec8a7a0211dbb3eb1bfeda78bc4e2"}, + {file = "debugpy-1.8.21-cp38-cp38-win_amd64.whl", hash = "sha256:aa9d941d6dfe3d0407e4b3ca0b9ec466030e260fbf1174094f68785680f66db6"}, + {file = "debugpy-1.8.21-cp39-cp39-macosx_15_0_x86_64.whl", hash = "sha256:9f5171176a0084b95d2ebe55a4d1f7b2a75b74c5dbec577ebd3a85c740551c36"}, + {file = "debugpy-1.8.21-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:f15c10084f9861b5e8414a48f18f8e4aadf51a98a59e72c16aa28281ca994672"}, + {file = "debugpy-1.8.21-cp39-cp39-win32.whl", hash = "sha256:4e70cc8b5079f885cb43910924ee0aab73b8b6b2a14eff23afdd9895d86e79eb"}, + {file = "debugpy-1.8.21-cp39-cp39-win_amd64.whl", hash = "sha256:e935f9dc0501be523c8a8e1853c39432e1354e9ece717ae5998fd2371c4542c3"}, + {file = "debugpy-1.8.21-py2.py3-none-any.whl", hash = "sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92"}, + {file = "debugpy-1.8.21.tar.gz", hash = "sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6"}, ] [[package]] @@ -1122,7 +1102,7 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "floris" -version = "4.6" +version = "4.6.6" description = "A controls-oriented engineering wake model." optional = false python-versions = ">=3.10, <3.15" @@ -1136,21 +1116,21 @@ coloredlogs = ">=15.0,<16.0" matplotlib = ">=3.0,<4.0" numexpr = ">=2.0,<3.0" numpy = ">=2.0,<3.0" -pandas = ">=2.0,<3.0" +pandas = ">=2.0,<4" pathos = ">=0.3,<1.0" pyyaml = ">=6.0,<7.0" scipy = ">=1.1,<2.0" shapely = ">=2.0,<3.0" [package.extras] -develop = ["isort (>=5,<8)", "pre-commit (>=4.0,<5.0)", "pytest (>=8,<10)", "pytest-benchmark (>=5.1,<6.0)", "ruff (>=0.9,<1.0)"] -docs = ["bokeh (>=3.7,<4.0)", "jupyter-book (>=1.0,<2.0)", "ruamel.yaml (>=0.18.0,<0.19.0)", "sphinx-autodoc-typehints (>=2,<4)", "sphinx-book-theme (>=1.0,<2.0)", "sphinxcontrib-autoyaml (>=1.0,<2.0)", "sphinxcontrib.mermaid (>=1.0,<2.0)"] +develop = ["isort (>=5,<9)", "pre-commit (>=4.0,<5.0)", "pytest (>=8,<10)", "pytest-benchmark (>=5.1,<6.0)", "ruff (>=0.9,<1.0)"] +docs = ["bokeh (>=3.7,<4.0)", "jupyter-book (>=1.0,<2.0)", "ruamel.yaml (>=0.18.0,<0.19.0)", "sphinx-autodoc-typehints (>=2,<4)", "sphinx-book-theme (>=1.0,<2.0)", "sphinxcontrib-autoyaml (>=1.0,<2.0)", "sphinxcontrib.mermaid (>=1,<3)"] [package.source] type = "git" url = "https://github.com/misi9170/floris.git" reference = "feature/user-def-op-mod" -resolved_reference = "ba521ed04c64234ad46fb35d66dadb0f9d6716ac" +resolved_reference = "27d5385eeb4e1a1bc88a95b41fcd52109bc78e0d" [[package]] name = "fonttools" @@ -1328,14 +1308,14 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "idna" -version = "3.15" +version = "3.18" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, - {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, + {file = "idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2"}, + {file = "idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848"}, ] [package.extras] @@ -1500,16 +1480,28 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "joblib" +version = "1.5.3" +description = "Lightweight pipelining with Python functions" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713"}, + {file = "joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3"}, +] + [[package]] name = "json5" -version = "0.14.0" +version = "0.15.0" description = "A Python implementation of the JSON5 data format." optional = false python-versions = ">=3.8.0" groups = ["dev"] files = [ - {file = "json5-0.14.0-py3-none-any.whl", hash = "sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a"}, - {file = "json5-0.14.0.tar.gz", hash = "sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb"}, + {file = "json5-0.15.0-py3-none-any.whl", hash = "sha256:56636a30c0e8a4665fe2179c0212f32eae3796dea89ea6f649b9436ecdb39618"}, + {file = "json5-0.15.0.tar.gz", hash = "sha256:7424d1f1eb1d56da6e3d70643f53619862b4ce81440bdb8ecfd6f875e5ba4a71"}, ] [[package]] @@ -1605,16 +1597,37 @@ jupyterlab = "*" nbconvert = "*" notebook = "*" +[[package]] +name = "jupyter-builder" +version = "1.0.2" +description = "JupyterLab build tools" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "jupyter_builder-1.0.2-py3-none-any.whl", hash = "sha256:b024f65d36e1d530542db597b00dd513261aa59842e0d0fbbb1015a9f1935e9c"}, + {file = "jupyter_builder-1.0.2.tar.gz", hash = "sha256:6155d78a5325010532a6419ffcba89eac643fd1aa56ea83115e661924d6f6aab"}, +] + +[package.dependencies] +jupyter-core = "*" +tomli = {version = "*", markers = "python_version < \"3.11\""} +traitlets = "*" + +[package.extras] +dev = ["build", "hatch", "mypy", "pre-commit", "ruff (==0.15.11)"] +test = ["copier (>=9.3,<10)", "coverage", "jinja2-time", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-cov"] + [[package]] name = "jupyter-client" -version = "8.8.0" +version = "8.9.1" description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a"}, - {file = "jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e"}, + {file = "jupyter_client-8.9.1-py3-none-any.whl", hash = "sha256:0b7a295bc46e8751e9adae84781f726c851c1d911bd793edc4a3bde942e3da81"}, + {file = "jupyter_client-8.9.1.tar.gz", hash = "sha256:a58f730dd9e728ba16ba1d62ebccf7ffe1ebbdbce4e95cfae941b7321ae1f4fa"}, ] [package.dependencies] @@ -1623,6 +1636,7 @@ python-dateutil = ">=2.8.2" pyzmq = ">=25.0" tornado = ">=6.4.1" traitlets = ">=5.3" +typing-extensions = ">=4.13.0" [package.extras] docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] @@ -1718,14 +1732,14 @@ jupyter_server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.18.2" +version = "2.20.0" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jupyter_server-2.18.2-py3-none-any.whl", hash = "sha256:fa5e46539ded65791838035a2b6001f13e54d5f64b8b3752eb1e91fdd641a5b8"}, - {file = "jupyter_server-2.18.2.tar.gz", hash = "sha256:06b4f40d8a7a00bb39d5216859c81374a0e7cfefe6d8a5a7facc5a5c37c679a7"}, + {file = "jupyter_server-2.20.0-py3-none-any.whl", hash = "sha256:c3b67c93c471e947c18b5026f04f21614218adb706df8f48227d3ee8e0a7cdcc"}, + {file = "jupyter_server-2.20.0.tar.gz", hash = "sha256:b5778ba337d8015a3dc2b80803ecdd5ac18d3797fddf61a50ea5fb472b4ebe14"}, ] [package.dependencies] @@ -1741,7 +1755,7 @@ nbformat = ">=5.3.0" overrides = {version = ">=5.0", markers = "python_version < \"3.12\""} packaging = ">=22.0" prometheus-client = ">=0.9" -pywinpty = {version = ">=2.0.1", markers = "os_name == \"nt\""} +pywinpty = {version = ">=2.0.1,<3.0.4 || >3.0.4", markers = "os_name == \"nt\""} pyzmq = ">=24" send2trash = ">=1.8.2" terminado = ">=0.8.3" @@ -1751,7 +1765,7 @@ websocket-client = ">=1.7" [package.extras] docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx (<9.0)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] -test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] +test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<10)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] [[package]] name = "jupyter-server-terminals" @@ -1775,14 +1789,14 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.5.7" +version = "4.6.1" description = "JupyterLab computational environment" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jupyterlab-4.5.7-py3-none-any.whl", hash = "sha256:fba4cb0e2c44a52859669d8c98b45de029d5e515f8407bf8534d2a8fc5f0964d"}, - {file = "jupyterlab-4.5.7.tar.gz", hash = "sha256:55a9822c4754da305f41e113452c68383e214dcf96de760146af89ce5d5117b0"}, + {file = "jupyterlab-4.6.1-py3-none-any.whl", hash = "sha256:85a58546c831f3dce6cf919468c26874c9065e99c42279fb4abb8e1b552a98bb"}, + {file = "jupyterlab-4.6.1.tar.gz", hash = "sha256:75315982ed28427edaa62bb85eadb5105e4043a757643c910efd787fe6ed0837"}, ] [package.dependencies] @@ -1790,22 +1804,21 @@ async-lru = ">=1.0.0" httpx = ">=0.25.0,<1" ipykernel = ">=6.5.0,<6.30.0 || >6.30.0" jinja2 = ">=3.0.3" +jupyter-builder = ">=1.0.2" jupyter-core = "*" jupyter-lsp = ">=2.0.0" -jupyter-server = ">=2.4.0,<3" +jupyter-server = ">=2.19.0,<3" jupyterlab-server = ">=2.28.0,<3" notebook-shim = ">=0.2" -packaging = "*" -setuptools = ">=41.1.0" +packaging = ">=23.2" tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.11.12)"] -docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<8.2.0)", "sphinx-copybutton"] -docs-screenshots = ["altair (==6.0.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.5)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.3.post1)", "matplotlib (==3.10.0)", "nbconvert (>=7.0.0)", "pandas (==2.2.3)", "scipy (==1.15.1)"] -test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.15.15)", "shellcheck-py"] +docs-screenshots = ["altair (==6.0.0)", "ipykernel (<7.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.5)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.3.post1)", "matplotlib (==3.10.0)", "nbconvert (>=7.0.0)", "pandas (==2.2.3)", "scipy (==1.15.1)"] +test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "pytest-xdist", "requests", "requests-cache", "virtualenv"] upgrade-extension = ["copier (>=9,<10)", "jinja2-time (<0.3)", "pydantic (<3.0)", "pyyaml-include (<3.0)", "tomli-w (<2.0)"] [[package]] @@ -2005,103 +2018,105 @@ regex = ["regex"] [[package]] name = "librt" -version = "0.11.0" +version = "0.13.0" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"}, - {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"}, - {file = "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"}, - {file = "librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"}, - {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"}, - {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"}, - {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"}, - {file = "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"}, - {file = "librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"}, - {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"}, - {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"}, - {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"}, - {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"}, - {file = "librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"}, - {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"}, - {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"}, - {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"}, - {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"}, - {file = "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"}, - {file = "librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"}, - {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"}, - {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"}, - {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"}, - {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"}, - {file = "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"}, - {file = "librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"}, - {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"}, - {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"}, - {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"}, - {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"}, - {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"}, - {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"}, - {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"}, - {file = "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"}, - {file = "librt-0.11.0-cp39-cp39-win32.whl", hash = "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"}, - {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"}, - {file = "librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"}, + {file = "librt-0.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:34e47058fcc69a313293d6dee94216a4f30c929ae6f2476e58c5ba635aa639d5"}, + {file = "librt-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dbdd5b6509d0c2a8fe72cf494c299a61dbd58142a90a4190664ae159e4a7b547"}, + {file = "librt-0.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e56ea4ee4df77585a6b5c138f6538680886024fa559f5b55bd14b12e98e67b2"}, + {file = "librt-0.13.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f1f9cc4d09a46d9cb3c2063ae100629d3f52a6517c3c08c2f4c9828261883929"}, + {file = "librt-0.13.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f125f5d46b20f89dc5587a55cc416b4ba2a5b2ffda36d048ee120e17598a653a"}, + {file = "librt-0.13.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2608d3b39f9e0b4a66a130d9150c615cba40a5090d25eeeaa225e0e46de8c0ac"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fd35e95ab5e45c3901d37110263c7db85a961110f5460588fe37f8c131f88a7"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5f31b0aa13c9b04370d4da6be1ab7779776b3a075cceb6747a39a4be85fe1e40"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0b795f5fc70fbbb787ceaf79bb3a0d627bcc33c53de51741755263ec406b775a"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36b306a623aaad96fe4b378692b54f9c0789fccd833b9851753d5fbf6138cfde"}, + {file = "librt-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a3762e75fcac8c9e4dacaaf438bffd9003e2ca2c531b756f3c0035deefa674c8"}, + {file = "librt-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:d63bae12a8aeb51380be3438e4dc4bd27354d0f8e19166b2f44e3e94d6f552dc"}, + {file = "librt-0.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1b5a7bbff495baedbd9b916c367d66854008f8f3b575908ded477c499dc60082"}, + {file = "librt-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34bc7938b9fdf14fe32a406c19c71faf894c5cee7e7474bd0be2f17200b82d14"}, + {file = "librt-0.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f40e56b61b41be5f7dec938cfeffd660668cf4b5e72c78e7bd671d66b7bc2c79"}, + {file = "librt-0.13.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:9c5d02b89de5acd0379a51ec44a89476fb03df6145442e1c8ecd6bee2f91b176"}, + {file = "librt-0.13.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7db9a3ff32ef5f7d1703d93831a3316cdf0b537de6a1cc03cc8fdd09b9194e89"}, + {file = "librt-0.13.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3dbb2a31882456cadc7053378e81ad7ed7693db4ac9f98ab5f81ef034aa8ec9f"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c6014e3c80f9c1fe268ef8b0e0ef113bac672cc032f2f93866e7ddad4f3e663d"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:091b60a4d2174fc1ec5c34cdc0b72efb6224753d76b7da61ebeab7a191aec8bd"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:66cb1138f384a191a6d75f986064841fcfdc0cea98f7bd9c9ab9b38049917588"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:17221a7569f8f292aa0014226e48aa25b8c2b08da18088cd230953d0ea0f9cd1"}, + {file = "librt-0.13.0-cp311-cp311-win32.whl", hash = "sha256:fc67741da44c6eaa90e01eafb586bbba9b51eb5b6ed381ee6f5ae72eb3316d21"}, + {file = "librt-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc99dfb62b23c9207c33d0be8a2e2af7a42e21e6ea388b380a0c948c7b88953b"}, + {file = "librt-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:40ccd13c252d3fe473ffc8a57be7565abc8b64cf1b108344c859d5164f7f3e0c"}, + {file = "librt-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30536798f4504c0fad0885b1d371b0539abb081e4570c9d7c641cb51141b49f0"}, + {file = "librt-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93d24ebb82aa4420b1409c389e7857bc35bd0b668007ac8172427d5c73cc8cc5"}, + {file = "librt-0.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb8a1adce42d8b75485a5d56a9623a50bcab995b6079f1dac59fc44034dd93d9"}, + {file = "librt-0.13.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0763ca2ab66058174f9dee426dc64f5e0a89c24a7df8d3fe3f1836c04e25de4b"}, + {file = "librt-0.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b222493da6e7b6199db9bd79502436cf5a27da3c1f7fa83c7e285444fc93fd03"}, + {file = "librt-0.13.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fadc63331f4388c3dc90090448f682a7e9feafc11481391c1e94f2f907a3976e"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:70d9c62a4cffd9f23396cd5ef93fc5d11b31596b9b7d6306074abe3d5fcf09bd"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66c0e7e6b02a155576df2c77ec933a70b72da726e248c494abf690923e624348"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ac04bcd3328eb91d99dfedf6a60d9c1f15d3434e6f6daf922f0420f7d90b85c7"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db327e7271e653c32040b85ae6188059c924b57d7e1e29f935523fa017cd4e82"}, + {file = "librt-0.13.0-cp312-cp312-win32.whl", hash = "sha256:860bd1d8ba48456ce08feaf8d343a8aaeb2fa086f2bcaa2a923fa3f7a3ff9aa3"}, + {file = "librt-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:e54a315caf843c8d77e388cadc56ea9ded569935ee2d2347d7ea94992e5aa6fa"}, + {file = "librt-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:c718e99a0992127af84385378460db624103b559ab260435abcfe77a4e4ed1c1"}, + {file = "librt-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a468951af16155824e88bdd8326ebe5bdb371f3ec0ac04642994b98201d914f3"}, + {file = "librt-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae01d8512cc17079e53425635327dbf3f7ff57a42c00dec348bf79791c56444c"}, + {file = "librt-0.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32c26893cd085c1efe83219e78d866da23fb20a066101b8f68210004361d224c"}, + {file = "librt-0.13.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5929da1981a46bcf4b28b1b9499905f0ff58e2419da402a048234e9783acbc4b"}, + {file = "librt-0.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b85d664d777bab6c0d709416cb42938251fda9e221b79e3a2215d85df5f4f9"}, + {file = "librt-0.13.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:531b2df3e9fe96b1fcf73a6d165921e4656be5f58d631d384ebce344298368db"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:109b84a9edf69ad89dc1f66358659e14a031baca95e3e5b0060bd903ede8efd6"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1304368a3e7ffc3e9db986796cc5326fdb5943a3567ecc137cff318e4240c0e7"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e4f9b472e7d308d94b62c801982065661158c6ed02790d6c7ddb4337cea0f9c1"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f836c37478f167a81200d8c8b2c920a22224564bed2c23d7aeec760965c367a"}, + {file = "librt-0.13.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:4000d961ff9598ac6ea603c6c836a5ed49bc205ade5fc378b998dfe1e2c36628"}, + {file = "librt-0.13.0-cp313-cp313-win32.whl", hash = "sha256:79e44cff71750d299d61a678e49995b0d5935a9cda238c2574daeca3ba536927"}, + {file = "librt-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:54dab44a847d5ad1acd05c8a83fe518ae685516ecf4d3f7cc6e3df2a66767650"}, + {file = "librt-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:d4cb6fbfdf874340ab5e51450753c0f817b6958a3621125ee695bbc3de866566"}, + {file = "librt-0.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:25218d94b1d2cbc0ba1d8a3f9dc9af578d9646e5ed16443a70cde1dfdcce6d71"}, + {file = "librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f26629539d4893c2957a16c41bb058e1e135c1f150f6a2e25ed047f64cf3f5c6"}, + {file = "librt-0.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4517d47b2b8af26975a406fba7d314de9696d864252e0257c6ea90238cfe27f"}, + {file = "librt-0.13.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f19e181de5b3a1148bb3420b8c4b0b0ea0fce6950099724ad151d6cea5acc180"}, + {file = "librt-0.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22034924f5b42d5a56371cf271771bfeaabf235a7a8b6264bef2d20013f786c6"}, + {file = "librt-0.13.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7897db4e95e22468bdda33d8e012ceacd0182abf001e6389d763f0def6286b9"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ce61b3746545029d4f5c17d6bd74b676254ad98433086c846ffb5e8fa73f007"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:46c330e82565962c761dbce7941be2cff7db674ee807455a8d0cadc5f9b759b0"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:375f5af8f99cbaa99dd293af986e3d57caabc9ba81a5d3f021603764854197a1"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9320d34c3376ae204b2cd176e8d4883a013934e0aef822f1aed9c536490c275d"}, + {file = "librt-0.13.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9af313c66157a69dc69ea0059a66961692250e0dc95af9c385a48ffb770a0d16"}, + {file = "librt-0.13.0-cp314-cp314-win32.whl", hash = "sha256:f2a7253458e34f33543551394ae4fe104b497ec2a65ac266074de64c1df82e37"}, + {file = "librt-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:a3dfe4edf10e8ed7e55b026a8bfc2c2a8704218b659cd4bffdf604fab966dc39"}, + {file = "librt-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:68a5faee4bba381cb93b5961f684a514cf0053cb92308ff9c792c2fea0b174c6"}, + {file = "librt-0.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a38fb81d8376dfa2f8963b265fec07637802b0d01e2a127c19c66cb070fb24f5"}, + {file = "librt-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d4c8d9bd5abce34b2e75edb3bf37ab0f34e49b1f915a40ae8468eb7c85bc5b46"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:387e2f1d27e89bffe0d3f520f0da0662c973fd607ca16c1808f8a5085419485e"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:4f6db193d2e5e0ed60359b9a5a682cd67205d0d3b1e459a867dd4b5c4e7eaa7a"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d38604854e8d22faadf683ec6c02bb0f886e2ba56ef981a1c36ee275f21ea22"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:371f7ce73026815dafd51c50ce38416e91428b28c4b2ec97cd39271164b0045c"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3aaedf52171bee90860704c560bc798fe83b76247df47568e0197e9b13c735a0"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:96bad8725a4f196a798366c25ce075d1f7543a4ec045ffc13e6a7ec095cdab04"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6bf6a559ffe4a93bbea6cf31ddf01a7fd9ba342ef51f27beb178e318b74acd61"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:301067672387902c55f94b51d5022304b36c966ea9fe1f21caab99a9bef487c9"}, + {file = "librt-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:5fdcf34f86de8fb66d7dc7589f96ba91c4aa46671200d400e6fd6f109a483f18"}, + {file = "librt-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:260c33e92263fa629b4f6d3c51967a1c2158fe6c33237aaa3ebeac586b085259"}, + {file = "librt-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2f281549a4c52ac7bb97997f14353f8bd0e53a34ca0dad1c905cfd0b4a58ae99"}, + {file = "librt-0.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f442e3954b1addc759faae22a7c9a3f1e16d7d1db3f484279dc27d62e06968fa"}, + {file = "librt-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e786428f291dd2d2f1cbfc0e0caa45a2e395fab0ad3e2c9314daa8873414390"}, + {file = "librt-0.13.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21b7ac084f701a9cdff6139745a6620579d65a9379ac2d9d50a86368b109e63c"}, + {file = "librt-0.13.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a6e556d6aba31c93dd97ce661d66614d2429c0a3923f9dc8f0af7e8df10223a4"}, + {file = "librt-0.13.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3657346f867469e962549435aa05fd15330b1d6a92829f8e27988e194382d005"}, + {file = "librt-0.13.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:791aa18a373b90da8ac3c44fc77544f33fdf53ae403acdce9b39f1c26b4a3b94"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d6fb0eaa108814581c4d3bfbd068c3fb6757812a81415008d1bae08267cca360"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a001519c315d5db40710f2665d32c4791f1d4779fc96a9423fd18d92c8b9ac7b"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:d9188caac26e47671b52836a5e2a49873a7fc11c673b0c122d22515f98bc14e1"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:05d96b80b95d3a2721b619f8982b8558848b04875bb4772fd54842b59f61dd97"}, + {file = "librt-0.13.0-cp39-cp39-win32.whl", hash = "sha256:c3cd253cf32fe4f4662960d6bf7d55cb8be0c31a5d644a4d48aeafebaff3409a"}, + {file = "librt-0.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:b15e26cc0fe622d0c67e98bee6ef6bc8f792e20ee3006aa12627a00463d9399f"}, + {file = "librt-0.13.0.tar.gz", hash = "sha256:1d2a610c14ac0d0750ee0a3ab8548e83155258387891caaca04def4bf7289781"}, ] [[package]] @@ -2225,6 +2240,7 @@ description = "Python plotting package" optional = false python-versions = ">=3.10" groups = ["main", "examples"] +markers = "python_version < \"3.11\"" files = [ {file = "matplotlib-3.10.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77210dce9cb8153dffc967efaae990543392563d5a376d4dd8539bebcb0ed217"}, {file = "matplotlib-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1e7698ac9868428e84d2c967424803b2472ff7167d9d6590d4204ed775343c3b"}, @@ -2297,6 +2313,74 @@ python-dateutil = ">=2.7" [package.extras] dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7,<10)"] +[[package]] +name = "matplotlib" +version = "3.11.0" +description = "Python plotting package" +optional = false +python-versions = ">=3.11" +groups = ["main", "examples"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "matplotlib-3.11.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f857524b442f0f36e641868ce2171aafa88cb0bc0644f4e1d8a5df9b32649fef"}, + {file = "matplotlib-3.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:57baa92fdc82948ed716eae6d2579d4d6f40965cd8d2f416755b4a72580a3233"}, + {file = "matplotlib-3.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:630eee0e67d35cce2019a0e670719f4816e3b86aff0fa72729f6c69786fceb45"}, + {file = "matplotlib-3.11.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5106c444d0bf966eee2853548c03772af4ab7199118e086c62fbac8ccb07c055"}, + {file = "matplotlib-3.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d7aea652b58e686444079be3376ef546bffa1eee9b9bb9c472b9fcf6cf410d3"}, + {file = "matplotlib-3.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:70a5b3e9a5dab708c0f039709ae7c68d5b4d254e291ef76492cdba230c8bb5e4"}, + {file = "matplotlib-3.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:3d68266213e73823ac3be90615bab0cf31f88851e114cdb1dd25dacf3b01e1a7"}, + {file = "matplotlib-3.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:06b5872e9cf11adc8f589ded3ce11bc3e1061ad498259664fabc1f6615beb918"}, + {file = "matplotlib-3.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0515d495124be3124340e59f164d901ed4484e2246a5b74cfa483cac3b80bd97"}, + {file = "matplotlib-3.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be5f93a1d21981bfb802ded0d77a0caa92d4342a47d45754fac77e314a506344"}, + {file = "matplotlib-3.11.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41635d7909d19e52e924a521dde6d8f670b0f53ab1d0e8c331fa831554f681d1"}, + {file = "matplotlib-3.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:94f5000f67ca9faa300863ea17f8bce9175cb67b88bec4bc7780502d53dd7c9e"}, + {file = "matplotlib-3.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac6f1ef39f3d0f9e2463303013094992cdbe0f85f43bc54155bc472b2042768e"}, + {file = "matplotlib-3.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:9dd11fb612ce7bc60b1de5b4fc87ff959d22317b5de42aabf392f66f97af22eb"}, + {file = "matplotlib-3.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce3b839b34ae1f430b4616893a2945a2999debaa7e94e7e29a2a8bbf286f7b5"}, + {file = "matplotlib-3.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:373db8f91214e8ccaf35ac833cc1dd59dd961e148bbd55dd027141591dde1313"}, + {file = "matplotlib-3.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be152b7570324dc8d01574cc9474dd2d803237acf528bcbb5b211fa347461a09"}, + {file = "matplotlib-3.11.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:126f256df600652d7e4b394cf3164ff75210a00038f287c95a012a6f58d0e83f"}, + {file = "matplotlib-3.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:03acfeddf87b0dddb11b081ef7740ad445a3ca8bcb6b8e3011b08f2cf802b75c"}, + {file = "matplotlib-3.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:ab3722f04f3ff34c23b5012c5873d2894174e06c3822fcdac3610965a5ac7d06"}, + {file = "matplotlib-3.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:c945824670fb8915b4ac879e5e61f3c58e0913022f70a0de4c082b17372f8771"}, + {file = "matplotlib-3.11.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3489c3dc487669b4a980bc3068f87856de7a1564248d3f6c629efb2a58b03f24"}, + {file = "matplotlib-3.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6a98f5476ce784a50ce09998f4ae1e6a9f25043cef8a480c98949902eda74620"}, + {file = "matplotlib-3.11.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:565af866fd63e4bd3f987d580afe27c44c2552a3b3305f4ecbb85133601ea6f3"}, + {file = "matplotlib-3.11.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6b3e64dea5062c570f04358e2711859f3531b459f29516274fbad889079e4f3"}, + {file = "matplotlib-3.11.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:942b37c5db1899610bd1543ce8e13e4ecff9a4633e7f63bb6aa9205d2644ebd1"}, + {file = "matplotlib-3.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c08e649a6313e1291e713623b97a38e5bb4aa580b2a100a94a3309bc6b9c8eb3"}, + {file = "matplotlib-3.11.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2746cd2c113742ff6ce37a864c5ac5fd7aa644568f445e66166e457ac78e40e0"}, + {file = "matplotlib-3.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3338e3e3de128cf50d0d2fb92a122815daf9c755bd882a474343c05f8fd7ec79"}, + {file = "matplotlib-3.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:25c2e5455efd8d99f41fb79871a31feb7d301569642e332ec58d72cfe9282bc3"}, + {file = "matplotlib-3.11.0-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9695457a467ff86d23f35037a43deb6f1134dd6d3e2ac8ce1e2087cff09ffb9"}, + {file = "matplotlib-3.11.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19c16c61dea63b3582918503e6b294193961261d9daa806d4ae2151f1ad05430"}, + {file = "matplotlib-3.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2d72ea8b7924f3cb955e61518d21e43b3df1e6c8a793b480a0c1214f185d30ba"}, + {file = "matplotlib-3.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:1c02da0a629dfa9debf52725ea06866b74c1fb70a895bae05e4493d34074f9f2"}, + {file = "matplotlib-3.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aa55d73b3117d4b07f959cd9eb6f69b375d8df3414139c479388e551aa5d999d"}, + {file = "matplotlib-3.11.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a9d8c6e7cd2f0ddf11d8d92e520dd1d9d2abb0cf6ac8831e338666c81e905847"}, + {file = "matplotlib-3.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:be050fcf32f729eda99f7f75a80bf67612ce16ab9ac1c23a387dcaede95cb70e"}, + {file = "matplotlib-3.11.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfabef0230d0697aa0d717385194dd41162e00207a68bf4abf94c2bf4c27dca0"}, + {file = "matplotlib-3.11.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1644db30e759199443493ac5e5caec24fdb775a8f6123021f85ba47c4133c3cb"}, + {file = "matplotlib-3.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15b0d160079cb10699a0e98b5989c70677b2df7cacdc62af67c30f2facec46d9"}, + {file = "matplotlib-3.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:446307e6b04b57b1f1239e228a1ec2af0d589a1008cebc3dfa3f5441d095cfb6"}, + {file = "matplotlib-3.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:652fb5696271d4c50f196d22a5ff4f8e4444c74f847423570d7dc0aa2bbd0159"}, + {file = "matplotlib-3.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:81ae77077a1e16d37a5b61096ccb07c8d90a99b518fa8256b8f21578932f2f62"}, + {file = "matplotlib-3.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ddef37840695f5eef65f9f070fe2d2f510f584c2156203f9f622a5b0584efffd"}, + {file = "matplotlib-3.11.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cf662e5ac5707658cb931e19972c4bd99f7b4f8b7bf79d3c821d239fa6b71e64"}, + {file = "matplotlib-3.11.0.tar.gz", hash = "sha256:68c0c7be01b30dcca3638934f7f591df73401235cbdbf0d1ab1c71e7db7f8b57"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +kiwisolver = ">=1.3.1" +numpy = ">=1.25" +packaging = ">=20.0" +pillow = ">=9" +pyparsing = ">=3" +python-dateutil = ">=2.7" + [[package]] name = "matplotlib-inline" version = "0.2.2" @@ -2317,14 +2401,14 @@ test = ["flake8", "matplotlib", "nbdime", "nbval", "notebook", "pytest"] [[package]] name = "mistune" -version = "3.2.1" +version = "3.3.3" description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "mistune-3.2.1-py3-none-any.whl", hash = "sha256:78cdb0ba5e938053ccf63651b352508d2efa9411dc8810bfb05f2dc5140c0048"}, - {file = "mistune-3.2.1.tar.gz", hash = "sha256:7c8e5501d38bac1582e067e46c8343f17d57ea1aaa735823f3aba1fd59c88a28"}, + {file = "mistune-3.3.3-py3-none-any.whl", hash = "sha256:99de1585e42dcbd826faa9e11a202727a5e202e4e4722a4c69ac1ff615793dd7"}, + {file = "mistune-3.3.3.tar.gz", hash = "sha256:c4c6c0c840b8637a2e9b8b6d607eb7c8f00888bf14c754409bcd339e848c2477"}, ] [package.dependencies] @@ -2465,21 +2549,21 @@ files = [ [[package]] name = "nbclient" -version = "0.10.4" +version = "0.11.0" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false python-versions = ">=3.10.0" groups = ["dev"] files = [ - {file = "nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440"}, - {file = "nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9"}, + {file = "nbclient-0.11.0-py3-none-any.whl", hash = "sha256:ef7fa0d59d6e1d41103933d8a445a18d5de860ca6b613b87b8574accdb3c2895"}, + {file = "nbclient-0.11.0.tar.gz", hash = "sha256:04a134a5b087f2c5887f228aca155db50169b8cd9334dee6942c8e927e56081a"}, ] [package.dependencies] -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -nbformat = ">=5.1.3" -traitlets = ">=5.4" +jupyter-client = ">=7.0.0" +jupyter-core = ">=5.4.0" +nbformat = ">=5.2.0" +traitlets = ">=5.13" [package.extras] dev = ["pre-commit"] @@ -2564,7 +2648,7 @@ description = "Provides an object-oriented python interface to the netCDF versio optional = false python-versions = ">=3.10" groups = ["main"] -markers = "platform_system == \"Windows\" and platform_machine == \"ARM64\" and python_version < \"3.11\"" +markers = "python_version < \"3.11\" and platform_system == \"Windows\" and platform_machine == \"ARM64\"" files = [ {file = "netcdf4-1.7.3-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:db761afd3a6b9482df018c4783e0bdf99141a41db1f14c68c89986effb182d57"}, {file = "netcdf4-1.7.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:ad4c2d9b469248d83cbacb70ad9e7d3a6c0ba27febe839c90192147199745ba4"}, @@ -2685,7 +2769,7 @@ description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = "!=3.14.1,>=3.11" groups = ["main"] -markers = "python_version >= \"3.11\" and python_version < \"3.14\"" +markers = "python_version < \"3.14\" and python_version >= \"3.11\"" files = [ {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, {file = "networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509"}, @@ -2704,19 +2788,20 @@ test-extras = ["pytest-mpl", "pytest-randomly"] [[package]] name = "notebook" -version = "7.5.6" +version = "7.6.0" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "notebook-7.5.6-py3-none-any.whl", hash = "sha256:4dde3f8fb55fa8fb7946d58c6e869ce9baf46d00fc070664f62604569d0faca0"}, - {file = "notebook-7.5.6.tar.gz", hash = "sha256:621174aade80108f0020b0f00738000b215f75fa3cd90771ad7aa0f24536a4e1"}, + {file = "notebook-7.6.0-py3-none-any.whl", hash = "sha256:98aa2811b54ac191321d5dfce12ca700f8a511a33a26e4de2fa106a357c43d6a"}, + {file = "notebook-7.6.0.tar.gz", hash = "sha256:ea13e79e601bf273074895fdfb17dd3f2da916d3c045e0b9c47d18b16ab62481"}, ] [package.dependencies] -jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.5.7,<4.6" +jupyter-builder = ">=1.0.2,<2" +jupyter-server = ">=2.19.0,<3" +jupyterlab = ">=4.6.0,<4.7" jupyterlab-server = ">=2.28.0,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" @@ -2724,7 +2809,7 @@ tornado = ">=6.2.0" [package.extras] dev = ["hatch", "pre-commit"] docs = ["myst-parser", "nbsphinx", "pydata-sphinx-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["importlib-resources (>=5.0) ; python_version < \"3.10\"", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.28.0,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] +test = ["ipykernel", "jupyter-server[test] (>=2.19.0,<3)", "jupyterlab-server[test] (>=2.28.0,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] [[package]] name = "notebook-shim" @@ -2887,7 +2972,7 @@ description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" groups = ["main", "examples"] -markers = "python_version >= \"3.11\"" +markers = "python_version == \"3.11\"" files = [ {file = "numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4"}, {file = "numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d"}, @@ -2963,6 +3048,61 @@ files = [ {file = "numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda"}, ] +[[package]] +name = "numpy" +version = "2.5.1" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.12" +groups = ["main", "examples"] +markers = "python_version >= \"3.12\"" +files = [ + {file = "numpy-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c889b56fe48b1018f764b0eec8df59ab654e9148aa91faa12596043500de277"}, + {file = "numpy-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab451b59c5643c570974c43aef780703ef1d3b4965d2be07afd530615a9358d1"}, + {file = "numpy-2.5.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:78798bd5b9ad744056af8efa90e3b9ddaa53272a0848a483084a1cc0a13b2dc0"}, + {file = "numpy-2.5.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2ae0ca40bcb22d6ba59c1dfd5446f49940b0f2d821fde133f10dda11f816b84e"}, + {file = "numpy-2.5.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61ac47e772e6b8ea489e1d2f441a34c5c3ac17327e7ce294cbdf535795ad4e75"}, + {file = "numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59fda5e192b570217ec2580c96f00e9a7e12ef6866a900eb089b62c1a32545ca"}, + {file = "numpy-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f7119ebff1a9829e9f431a4f9d28e703023bb6b9fe7c8f724467dbfc27c94ab3"}, + {file = "numpy-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e824c2acf8862052246be5a44c15da1777940c60d010dd2aab897824d9c430f9"}, + {file = "numpy-2.5.1-cp312-cp312-win32.whl", hash = "sha256:08d60c810432eb83360958dea0999ac4cfb94531ea8efcbf0b7f277c2068aeb2"}, + {file = "numpy-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7d60026c0bdb1380e83bfa7a0419c4577ee4b9a08880afcb6dadeb74c649fa2"}, + {file = "numpy-2.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:17a25e09640602e10bc8de0e6fa2b3fd68eedd84ba6d7842dc8f32f9ab87bd0b"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0bfebd8695f9863592fe744be833a258120b14a9f39da255e8aa8fade2c0ddd1"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30b44a6b53a7ae63c54c089a8726e5563ed302716c5b7ccc85afade40b0e7ff6"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:6165343f81b56ef8f514f396989e529b61d9dc709b99421b07e9f3e698e2287d"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4939237038ada79308dda3204ac6462df056b5672b2e25db1149cf873668b3e1"}, + {file = "numpy-2.5.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c6759f538fb912fc46de0a6b1758ccf7b57bc7c7ebebc23974fdac3de8db0cd"}, + {file = "numpy-2.5.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9726558e8db4a5bf7929a70ae50f63abda4daf0efe810e3bfbab95976f75fc1a"}, + {file = "numpy-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3935f3b419b244a02732676fa5317a9193cc596a4c0646db07e5b421229ac9f7"}, + {file = "numpy-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc932a65ded7ce9013d120845a2514dcccb1a67bfc8deb8d37633762951904a6"}, + {file = "numpy-2.5.1-cp313-cp313-win32.whl", hash = "sha256:4b4ff1608417eb7a59da7b967bbb798cacfe071d2caf526a24281cd562072ed9"}, + {file = "numpy-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:6c3fe51bc6a16453d452997053454f309e8e0ed7b42d6b361ce4ac8c32913d74"}, + {file = "numpy-2.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f7feb014281029e628ba2d5a007407443b06e418b6fe451d1e2adcbc8eba0107"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7c786fe9a5bbe360022e584c5a34cf6b54265c71bd7ec8ac3d8fec38968071f8"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32985c896d897419ef8da6917872d80b78ad0ea26d85b23245c7366ffde76d75"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:efd736408cc97c79b9e6917338dfc8f06013b2274f992e96b1d9a81a71e2a2c2"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ab84dc6b074fa881cae55bea94cc4f68e285181ba7f32497bf7dee6b1496165b"}, + {file = "numpy-2.5.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caf3e317d33d60c37986b452613f4ab51246d0691350c03d0cb4a898627f4a95"}, + {file = "numpy-2.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54ad769f17bc2d833b620851989f62054fb9ab93c969d9e1dc3c8e3d56beea21"}, + {file = "numpy-2.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c12afb53450fa976d4c681c50a7423729a4c51c0465ed9f32b8a9cabbc472373"}, + {file = "numpy-2.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c11c405efc5ff6816d5983c96cdfa215bab3428961243af3ff59b228490438"}, + {file = "numpy-2.5.1-cp314-cp314-win32.whl", hash = "sha256:f2479a47f8d5932d1718168a681ad6e536a9df484c83cfcf9de365e164537ace"}, + {file = "numpy-2.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:24d0eb82c0541d3415a33425db64ae439dffccd7b4dbcb30e7c35120205c506a"}, + {file = "numpy-2.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:5a4c988b38d261deeeaad9954e3deb091ad905c94e8bb6708654ef1d97f286b0"}, + {file = "numpy-2.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a33276be12fa045805f477f22482088b66bb758ffbe89a9d21457de863a32e22"}, + {file = "numpy-2.5.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f089d7b00756190aacf1f5d34bdf38c3c430ac82b4f868f8cede73380460fce7"}, + {file = "numpy-2.5.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:09e9bfd8d2cf479c7d174804fb3811c53a8e9f20a37444008606b57d6b7a826d"}, + {file = "numpy-2.5.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e68d8dd1e7eba712948f2053a29ec86917bc70ba1358df869d9f06649ef9cf09"}, + {file = "numpy-2.5.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99d5095fa265a0c4152e7bb12759e14381ef5496152f1ce58f44bdf55c44beb4"}, + {file = "numpy-2.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ab87a91b3cc3382b8956095bd8f95e00cf679bb81554339be1a2ba404a1473c1"}, + {file = "numpy-2.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:224ca51130ef7da85bea2191625181cb4f337f9cb64b471f10c1a12aa8b60077"}, + {file = "numpy-2.5.1-cp314-cp314t-win32.whl", hash = "sha256:6eab239876581b2b3c5a242281b6007bbdbcd1c7085d7709bb57c5929b11e6bf"}, + {file = "numpy-2.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:83ce9c80d5b521b0d77ddcbe5447c218d247929b6cc056ca5351342accfff0af"}, + {file = "numpy-2.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:5a6db61f9aaa57e369905c67d852045d3c4f7126405b29d09b19dec118e9c9cb"}, + {file = "numpy-2.5.1.tar.gz", hash = "sha256:a48a113e6afea91f5608793bafa7ef2ad481fefbda87ec5069f483de61cb9fa3"}, +] + [[package]] name = "openfast-io" version = "5.0.0" @@ -2988,14 +3128,14 @@ xlrd = ["xlrd (>2.0)"] [[package]] name = "openmdao" -version = "3.43.0" +version = "3.44.0" description = "OpenMDAO framework infrastructure" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "openmdao-3.43.0-py3-none-any.whl", hash = "sha256:fc98acea841df58710ffd2bfe1f34692901272ddd10b603522e7f37955259093"}, - {file = "openmdao-3.43.0.tar.gz", hash = "sha256:be5990817751f3897eb561e6c331feff9998fbea637db4718e54dfa01e477b1b"}, + {file = "openmdao-3.44.0-py3-none-any.whl", hash = "sha256:4494b7c04d09751c60053c1fc2098bf05c93298deb98011ae66f09167601113c"}, + {file = "openmdao-3.44.0.tar.gz", hash = "sha256:2aea7aafe3f4bda5052607654ecc719bcca48aaa2f7e88471bcf1a382b3a6c5d"}, ] [package.dependencies] @@ -3006,8 +3146,8 @@ requests = "*" scipy = ">=1.13" [package.extras] -all = ["aiounittest", "bokeh (>=3.4.0)", "colorama", "coverage (>=7.6.0)", "idna (>=3.7)", "ipympl", "ipyparallel", "jax (>=0.4.0)", "jaxlib (>=0.4.0)", "jinja2 (>=3.1.4)", "jupyter-book (>=1.0.3,<2)", "matplotlib", "notebook", "num2words", "numpydoc (>=1.1)", "panel", "parameterized", "playwright (>=1.20)", "pre-commit", "pycodestyle (>=2.4.0)", "pydocstyle (>=2.0.0)", "pydoe3", "rich", "sphinx-sitemap", "testflo (>=1.3.6)", "tqdm (>=4.66.3)", "websockets (>8)"] -docs = ["idna (>=3.7)", "ipyparallel", "jinja2 (>=3.1.4)", "jupyter-book (>=1.0.3,<2)", "matplotlib", "numpydoc (>=1.1)", "sphinx-sitemap", "tqdm (>=4.66.3)"] +all = ["aiounittest", "bokeh (>=3.4.0)", "colorama", "coverage (>=7.6.0)", "idna (>=3.7)", "ipympl", "ipyparallel", "jax (>=0.4.0)", "jaxlib (>=0.4.0)", "jinja2 (>=3.1.4)", "jupyter-book (>=1.0.3,<2)", "matplotlib", "notebook", "num2words", "numpydoc (>=1.1)", "panel", "parameterized", "playwright (>=1.20)", "pre-commit", "pycodestyle (>=2.4.0)", "pydata-sphinx-theme (>=0.15.0,<0.16.0)", "pydocstyle (>=2.0.0)", "pydoe3", "rich", "sphinx-sitemap", "testflo (>=1.3.6)", "tqdm (>=4.66.3)", "websockets (>8)"] +docs = ["idna (>=3.7)", "ipyparallel", "jinja2 (>=3.1.4)", "jupyter-book (>=1.0.3,<2)", "matplotlib", "numpydoc (>=1.1)", "pydata-sphinx-theme (>=0.15.0,<0.16.0)", "sphinx-sitemap", "tqdm (>=4.66.3)"] doe = ["pydoe3"] jax = ["jax (>=0.4.0)", "jaxlib (>=0.4.0)"] julia = ["omjlcomps (>=0.2.6)"] @@ -3109,6 +3249,7 @@ description = "Powerful data structures for data analysis, time series, and stat optional = false python-versions = ">=3.9" groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, @@ -3168,11 +3309,7 @@ files = [ ] [package.dependencies] -numpy = [ - {version = ">=1.22.4", markers = "python_version < \"3.11\""}, - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, -] +numpy = {version = ">=1.22.4", markers = "python_version < \"3.11\""} python-dateutil = ">=2.8.2" pytz = ">=2020.1" tzdata = ">=2022.7" @@ -3202,6 +3339,99 @@ sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-d test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.9.2)"] +[[package]] +name = "pandas" +version = "3.0.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.11" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:455f6f8139d4282188f526868dbc3c828470e88a3d9d59a891bd46a455f21b98"}, + {file = "pandas-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4e15135e2ee5df1063313e2425ceef8ac0f4ae775893815b0923651b806a5639"}, + {file = "pandas-3.0.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:05f1f1752b8533ea03f7f39a9c15b1a058d067bb48f4748948e7a8691e0510f2"}, + {file = "pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a1e45c80cceb3b4a21bc5939d52e8cbd8d9b7305309219d59e9754d9ce09e27"}, + {file = "pandas-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:14da8316da4d0c5a77618425996bfb1248ca87fc2c1486e6fde4652bd18b5824"}, + {file = "pandas-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a55066a0505dae0ba2b50a46637db34b46f9094c65c5d4800794ef6335010938"}, + {file = "pandas-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6674ab18ad8c57802867264b00e15e7bb904700cdd9046e3b2fa1fce237439ea"}, + {file = "pandas-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:5cc09a68b3120e0f54870dede8287a7bb1fa463907e4fcec1ea77cab6179bf7a"}, + {file = "pandas-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09"}, + {file = "pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4"}, + {file = "pandas-3.0.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c"}, + {file = "pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9"}, + {file = "pandas-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf"}, + {file = "pandas-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c"}, + {file = "pandas-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc"}, + {file = "pandas-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49"}, + {file = "pandas-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa"}, + {file = "pandas-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7"}, + {file = "pandas-3.0.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8"}, + {file = "pandas-3.0.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a"}, + {file = "pandas-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb"}, + {file = "pandas-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2"}, + {file = "pandas-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44"}, + {file = "pandas-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e"}, + {file = "pandas-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d"}, + {file = "pandas-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066"}, + {file = "pandas-3.0.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd"}, + {file = "pandas-3.0.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085"}, + {file = "pandas-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870"}, + {file = "pandas-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f"}, + {file = "pandas-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13"}, + {file = "pandas-3.0.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3650109c0f22879df8bd6179ab9ee3d7f1d1d4e7e0094a3f0032d9f51e2e64ac"}, + {file = "pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f"}, + {file = "pandas-3.0.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba7e08b9ac1d54569cd1e256e3668975ed624d6826f7b68df0342b012007bddb"}, + {file = "pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a"}, + {file = "pandas-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3a2ec42c98ffa2565a67e08e218d06d72576d758d90facb7c00805194d8f360"}, + {file = "pandas-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:335f62418ed562cfc3c49e9e196375c28b729dcef8543abf4f9438e381bf3c76"}, + {file = "pandas-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5"}, + {file = "pandas-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:a2d2dff8a04f3917b55ab3910c32990f8ddf7eceba114947838cefa976a68977"}, + {file = "pandas-3.0.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:0d589105b3c14645af1738ff279b2995102d8f7a03b0a66dc8d95550eb513e04"}, + {file = "pandas-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:13fc1e853d9e04743d11ba75a985ccbc2a317fe07d8af61e445a6fd24dacd6a6"}, + {file = "pandas-3.0.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:819959dab7bbd0049c15623fbac4e29a191b9528160a61fb1032242d8ced2d9c"}, + {file = "pandas-3.0.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:60ae316d3fd75d1858d450d0db0103ea2be3e7d4a95ec2f064f7e2ae63f7b028"}, + {file = "pandas-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd3a518890b400d32f9023722dc9a9a5c969f00b415419a3c06c043f09bb5d7d"}, + {file = "pandas-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9c39be2d709d01fa972a0cabc522389fceca4f3969332ba25a7d6c5802cf976a"}, + {file = "pandas-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4db8c527972a821cf5286b40ccc57642a39bc62e62022b42f99f8a67fca8c3a1"}, + {file = "pandas-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1"}, + {file = "pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.26.0", markers = "python_version < \"3.14\""}, + {version = ">=2.3.3", markers = "python_version >= \"3.14\""}, +] +python-dateutil = ">=2.8.2" +tzdata = {version = "*", markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\""} + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)", "beautifulsoup4 (>=4.12.3)", "bottleneck (>=1.4.2)", "fastparquet (>=2024.11.0)", "fsspec (>=2024.10.0)", "gcsfs (>=2024.10.0)", "html5lib (>=1.1)", "hypothesis (>=6.116.0)", "jinja2 (>=3.1.5)", "lxml (>=5.3.0)", "matplotlib (>=3.9.3)", "numba (>=0.60.0)", "numexpr (>=2.10.2)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "psycopg2 (>=2.9.10)", "pyarrow (>=13.0.0)", "pyiceberg (>=0.8.1)", "pymysql (>=1.1.1)", "pyreadstat (>=1.2.8)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)", "python-calamine (>=0.3.0)", "pytz (>=2020.1)", "pyxlsb (>=1.0.10)", "qtpy (>=2.4.2)", "s3fs (>=2024.10.0)", "scipy (>=1.14.1)", "tables (>=3.10.1)", "tabulate (>=0.9.0)", "xarray (>=2024.10.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)", "zstandard (>=0.23.0)"] +aws = ["s3fs (>=2024.10.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.4.2)"] +compression = ["zstandard (>=0.23.0)"] +computation = ["scipy (>=1.14.1)", "xarray (>=2024.10.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "python-calamine (>=0.3.0)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)"] +feather = ["pyarrow (>=13.0.0)"] +fss = ["fsspec (>=2024.10.0)"] +gcp = ["gcsfs (>=2024.10.0)"] +hdf5 = ["tables (>=3.10.1)"] +html = ["beautifulsoup4 (>=4.12.3)", "html5lib (>=1.1)", "lxml (>=5.3.0)"] +iceberg = ["pyiceberg (>=0.8.1)"] +mysql = ["SQLAlchemy (>=2.0.36)", "pymysql (>=1.1.1)"] +output-formatting = ["jinja2 (>=3.1.5)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=13.0.0)"] +performance = ["bottleneck (>=1.4.2)", "numba (>=0.60.0)", "numexpr (>=2.10.2)"] +plot = ["matplotlib (>=3.9.3)"] +postgresql = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "psycopg2 (>=2.9.10)"] +pyarrow = ["pyarrow (>=13.0.0)"] +spss = ["pyreadstat (>=1.2.8)"] +sql-other = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)"] +test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)"] +timezone = ["pytz (>=2020.1)"] +xml = ["lxml (>=5.3.0)"] + [[package]] name = "pandocfilters" version = "1.5.1" @@ -3301,103 +3531,99 @@ ptyprocess = ">=0.5" [[package]] name = "pillow" -version = "12.2.0" +version = "12.3.0" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" groups = ["main", "examples"] files = [ - {file = "pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f"}, - {file = "pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c"}, - {file = "pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3"}, - {file = "pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa"}, - {file = "pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032"}, - {file = "pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5"}, - {file = "pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024"}, - {file = "pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab"}, - {file = "pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176"}, - {file = "pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b"}, - {file = "pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909"}, - {file = "pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808"}, - {file = "pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60"}, - {file = "pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe"}, - {file = "pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5"}, - {file = "pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780"}, - {file = "pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5"}, - {file = "pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5"}, - {file = "pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940"}, - {file = "pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5"}, - {file = "pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414"}, - {file = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c"}, - {file = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2"}, - {file = "pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c"}, - {file = "pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795"}, - {file = "pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3"}, - {file = "pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9"}, - {file = "pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795"}, - {file = "pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e"}, - {file = "pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b"}, - {file = "pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06"}, - {file = "pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b"}, - {file = "pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4"}, - {file = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4"}, - {file = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea"}, - {file = "pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24"}, - {file = "pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98"}, - {file = "pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453"}, - {file = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8"}, - {file = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b"}, - {file = "pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295"}, - {file = "pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed"}, - {file = "pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286"}, - {file = "pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50"}, - {file = "pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104"}, - {file = "pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7"}, - {file = "pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150"}, - {file = "pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1"}, - {file = "pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463"}, - {file = "pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e"}, - {file = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06"}, - {file = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43"}, - {file = "pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354"}, - {file = "pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1"}, - {file = "pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e"}, - {file = "pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5"}, + {file = "pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a"}, + {file = "pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7"}, + {file = "pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f"}, + {file = "pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec"}, + {file = "pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468"}, + {file = "pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed"}, + {file = "pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1"}, + {file = "pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb"}, + {file = "pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f"}, + {file = "pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756"}, + {file = "pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6"}, + {file = "pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd"}, + {file = "pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd"}, + {file = "pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c"}, + {file = "pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5"}, + {file = "pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b"}, + {file = "pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a"}, + {file = "pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26"}, + {file = "pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965"}, + {file = "pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7"}, + {file = "pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9"}, + {file = "pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91"}, + {file = "pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c"}, + {file = "pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df"}, + {file = "pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f"}, + {file = "pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09"}, + {file = "pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec"}, + {file = "pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66"}, + {file = "pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35"}, + {file = "pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65"}, + {file = "pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3"}, + {file = "pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a"}, + {file = "pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e"}, + {file = "pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f"}, + {file = "pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8"}, + {file = "pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930"}, + {file = "pillow-12.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8"}, + {file = "pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0"}, + {file = "pillow-12.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321"}, + {file = "pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b"}, + {file = "pillow-12.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198"}, + {file = "pillow-12.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130"}, + {file = "pillow-12.3.0-cp314-cp314-win32.whl", hash = "sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a"}, + {file = "pillow-12.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d"}, + {file = "pillow-12.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838"}, + {file = "pillow-12.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e"}, + {file = "pillow-12.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17"}, + {file = "pillow-12.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385"}, + {file = "pillow-12.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c"}, + {file = "pillow-12.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d"}, + {file = "pillow-12.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931"}, + {file = "pillow-12.3.0-cp314-cp314t-win32.whl", hash = "sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7"}, + {file = "pillow-12.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c"}, + {file = "pillow-12.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c"}, + {file = "pillow-12.3.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f"}, + {file = "pillow-12.3.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701"}, + {file = "pillow-12.3.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace"}, + {file = "pillow-12.3.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4"}, + {file = "pillow-12.3.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39"}, + {file = "pillow-12.3.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71"}, + {file = "pillow-12.3.0-cp315-cp315-win32.whl", hash = "sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827"}, + {file = "pillow-12.3.0-cp315-cp315-win_amd64.whl", hash = "sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5"}, + {file = "pillow-12.3.0-cp315-cp315-win_arm64.whl", hash = "sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658"}, + {file = "pillow-12.3.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf"}, + {file = "pillow-12.3.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64"}, + {file = "pillow-12.3.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e"}, + {file = "pillow-12.3.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777"}, + {file = "pillow-12.3.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1"}, + {file = "pillow-12.3.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9"}, + {file = "pillow-12.3.0-cp315-cp315t-win32.whl", hash = "sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8"}, + {file = "pillow-12.3.0-cp315-cp315t-win_amd64.whl", hash = "sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418"}, + {file = "pillow-12.3.0-cp315-cp315t-win_arm64.whl", hash = "sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a"}, + {file = "pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce"}, ] [package.extras] @@ -3405,19 +3631,19 @@ docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybut fpx = ["olefile"] mic = ["olefile"] test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"] -tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma (>=5)", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] +tests = ["coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "setuptools", "trove-classifiers (>=2024.10.12)"] xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.9.6" +version = "4.10.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917"}, - {file = "platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a"}, + {file = "platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a"}, + {file = "platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7"}, ] [[package]] @@ -3574,7 +3800,7 @@ description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" groups = ["dev"] -markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\" or os_name != \"nt\"" +markers = "os_name != \"nt\" or sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -3698,14 +3924,14 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "python-benedict" -version = "0.37.0" +version = "0.38.0" description = "python-benedict is a dict subclass with keylist/keypath/keyattr support, normalized I/O operations (base64, csv, ini, json, pickle, plist, query-string, toml, xls, xml, yaml) and many utilities... for humans, obviously." optional = false python-versions = "*" groups = ["main"] files = [ - {file = "python_benedict-0.37.0-py3-none-any.whl", hash = "sha256:532ac2d94cfbfef7269984132e42a0b55330ab4275267958ce07301251da46cc"}, - {file = "python_benedict-0.37.0.tar.gz", hash = "sha256:d2c7d711f45fbb8fdc128c0463b6ad654d68f0c9caeeedd13ed37e5048fc04f3"}, + {file = "python_benedict-0.38.0-py3-none-any.whl", hash = "sha256:5f4cbdfdda245d3f2899a7fd9d59ee68e69e6d1e0d57693f8626f186a11fcc6b"}, + {file = "python_benedict-0.38.0.tar.gz", hash = "sha256:71e066b73f15d2231927b3021469a1db57a3e96092a99917018b63f51329e49c"}, ] [package.dependencies] @@ -3715,12 +3941,12 @@ typing_extensions = ">=4.13.2,<4.16.0" [package.extras] all = ["python-benedict[io,parse,s3,schema]"] html = ["beautifulsoup4 (>=4.12.0,<5.0.0)", "python-benedict[xml]"] -io = ["python-benedict[html,toml,xls,xml,yaml]", "python-fsutil (>=0.16.1,<1.0.0)", "requests (>=2.33.0,<3.0.0)"] +io = ["python-benedict[html,toml,xls,xml,yaml]", "python-fsutil (>=0.17.0,<1.0.0)", "requests (>=2.33.0,<3.0.0)"] parse = ["ftfy (>=6.0.0,<7.0.0)", "mailchecker (>=4.1.0,<7.0.0)", "phonenumbers (>=8.12.0,<10.0.0)", "python-dateutil (>=2.8.0,<3.0.0)"] -s3 = ["boto3 (>=1.24.89,<2.0.0)", "python-fsutil (>=0.16.1,<1.0.0)"] +s3 = ["boto3 (>=1.24.89,<2.0.0)", "python-fsutil (>=0.17.0,<1.0.0)"] schema = ["pydantic (>=2.0.0,<3.0.0)"] toml = ["tomli (>=2.0.0,<3.0.0) ; python_version < \"3.11\"", "tomli-w (>=1.0.0,<2.0.0)"] -xls = ["openpyxl (>=3.0.0,<4.0.0)", "python-fsutil (>=0.16.1,<1.0.0)", "xlrd (>=2.0.0,<3.0.0)"] +xls = ["openpyxl (>=3.0.0,<4.0.0)", "python-fsutil (>=0.17.0,<1.0.0)", "xlrd (>=2.0.0,<3.0.0)"] xml = ["xmltodict (>=0.12.0,<2.0.0)"] yaml = ["pyyaml (>=6.0,<7.0)"] @@ -3779,6 +4005,7 @@ description = "World timezone definitions, modern and historical" optional = false python-versions = "*" groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126"}, {file = "pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a"}, @@ -3786,29 +4013,28 @@ files = [ [[package]] name = "pywinpty" -version = "3.0.3" +version = "3.0.5" description = "Pseudo terminal support for Windows from Python." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] markers = "os_name == \"nt\"" files = [ - {file = "pywinpty-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:ff05f12d775b142b11c6fe085129bdd759b61cf7d41da6c745e78e3a1ef5bf40"}, - {file = "pywinpty-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:340ccacb4d74278a631923794ccd758471cfc8eeeeee4610b280420a17ad1e82"}, - {file = "pywinpty-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:dff25a9a6435f527d7c65608a7e62783fc12076e7d44487a4911ee91be5a8ac8"}, - {file = "pywinpty-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:fbc1e230e5b193eef4431cba3f39996a288f9958f9c9f092c8a961d930ee8f68"}, - {file = "pywinpty-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c9081df0e49ffa86d15db4a6ba61530630e48707f987df42c9d3313537e81fc0"}, - {file = "pywinpty-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:15e79d870e18b678fb8a5a6105fd38496b55697c66e6fc0378236026bc4d59e9"}, - {file = "pywinpty-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9c91dbb026050c77bdcef964e63a4f10f01a639113c4d3658332614544c467ab"}, - {file = "pywinpty-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:fe1f7911805127c94cf51f89ab14096c6f91ffdcacf993d2da6082b2142a2523"}, - {file = "pywinpty-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:3f07a6cf1c1d470d284e614733c3d0f726d2c85e78508ea10a403140c3c0c18a"}, - {file = "pywinpty-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:15c7c0b6f8e9d87aabbaff76468dabf6e6121332c40fc1d83548d02a9d6a3759"}, - {file = "pywinpty-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:d4b6b7b0fe0cdcd02e956bd57cfe9f4e5a06514eecf3b5ae174da4f951b58be9"}, - {file = "pywinpty-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:34789d685fc0d547ce0c8a65e5a70e56f77d732fa6e03c8f74fefb8cbb252019"}, - {file = "pywinpty-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0c37e224a47a971d1a6e08649a1714dac4f63c11920780977829ed5c8cadead1"}, - {file = "pywinpty-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c4e9c3dff7d86ba81937438d5819f19f385a39d8f592d4e8af67148ceb4f6ab5"}, - {file = "pywinpty-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:0f10e81d52d7f2c4d927f645f247028e64eaf205a3ed9e64dbd998122108a218"}, - {file = "pywinpty-3.0.3.tar.gz", hash = "sha256:523441dc34d231fb361b4b00f8c99d3f16de02f5005fd544a0183112bcc22412"}, + {file = "pywinpty-3.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:b467dcad72365bc2205ed8b6e694e817d71de269d46e56cfe267dfa9d3d30e1b"}, + {file = "pywinpty-3.0.5-cp310-cp310-win_arm64.whl", hash = "sha256:7dc4046ea8e4d7f0a16dae8dfcaeeda6df7ca3a9330444d2ba5bb96138fe0a91"}, + {file = "pywinpty-3.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:af7a8720c78776ddd6259b71dd567944f766a6cd67f8d2887fbc4973967bacda"}, + {file = "pywinpty-3.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:c2406f54f699eab75953fb75ce805f2ae55a33a957cd070890abd454fb4b7680"}, + {file = "pywinpty-3.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:d62946adf14b15b54c0b8d785f93fe18b04da23f4ad59e2e8c4612646e9abd23"}, + {file = "pywinpty-3.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:e9391c05fbfa7a992a97e831fc6849887b4014a614192e3d984a7ca59592b376"}, + {file = "pywinpty-3.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:48db1b0ad9d0a1b81dcaaa7163a99a7808deaceb0c1b2344716dc1fc090c3c4c"}, + {file = "pywinpty-3.0.5-cp313-cp313-win_arm64.whl", hash = "sha256:2c6008fb2d3774b48693b2fcb7f2cc317ade9dc581289a964ffeeaf81307c9b5"}, + {file = "pywinpty-3.0.5-cp313-cp313t-win_amd64.whl", hash = "sha256:22ce1b780d89821cc52daf6eac0708af22d93d000ce9c7c07e37489db8594598"}, + {file = "pywinpty-3.0.5-cp313-cp313t-win_arm64.whl", hash = "sha256:9c2919a81bc5cfb09b86fc5a002112b2de95ca4304a07413cbeeb746a1307a5c"}, + {file = "pywinpty-3.0.5-cp314-cp314-win_amd64.whl", hash = "sha256:03bb3c16d691d9242267201830bcd0e64a9b663170e9042bc84b210da9de15ac"}, + {file = "pywinpty-3.0.5-cp314-cp314-win_arm64.whl", hash = "sha256:89c5c6ef08997a3b4b277b214a35fe15cab4dd6d119f0140aa71df5b1168fdbc"}, + {file = "pywinpty-3.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:7b566165e0c5fdd6abe167a5ac8b954be6a843eb55a85946576d6bc1dea03d6d"}, + {file = "pywinpty-3.0.5-cp314-cp314t-win_arm64.whl", hash = "sha256:24366280a8aa677323da87bec729cb3ea3b35367386cece0978bdc6e4695c690"}, + {file = "pywinpty-3.0.5.tar.gz", hash = "sha256:61db0db063de9865adbea66db294628f8577f608d9764a4c7d3384eeacc4e81b"}, ] [[package]] @@ -4158,6 +4384,7 @@ description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" groups = ["main", "dev"] +markers = "python_version < \"3.11\"" files = [ {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, @@ -4276,6 +4503,133 @@ files = [ {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, ] +[[package]] +name = "rpds-py" +version = "2026.6.3" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.11" +groups = ["main", "dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7"}, + {file = "rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da"}, + {file = "rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4"}, + {file = "rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6"}, + {file = "rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93"}, + {file = "rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a"}, + {file = "rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127"}, + {file = "rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804"}, + {file = "rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0"}, + {file = "rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4"}, + {file = "rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa"}, + {file = "rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc"}, + {file = "rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822"}, + {file = "rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed"}, + {file = "rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f"}, + {file = "rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96"}, + {file = "rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223"}, + {file = "rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4"}, + {file = "rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7"}, + {file = "rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d"}, + {file = "rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97"}, + {file = "rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0"}, + {file = "rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80"}, + {file = "rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb"}, + {file = "rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e"}, + {file = "rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77"}, + {file = "rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698"}, + {file = "rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd"}, + {file = "rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d"}, + {file = "rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8"}, + {file = "rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5"}, + {file = "rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2"}, + {file = "rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13"}, + {file = "rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868"}, + {file = "rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187"}, + {file = "rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107"}, + {file = "rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba"}, + {file = "rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369"}, + {file = "rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146"}, + {file = "rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826"}, + {file = "rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4"}, +] + [[package]] name = "ruamel-yaml" version = "0.19.1" @@ -4393,7 +4747,7 @@ description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.11" groups = ["main"] -markers = "python_version >= \"3.11\"" +markers = "python_version == \"3.11\"" files = [ {file = "scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec"}, {file = "scipy-1.17.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696"}, @@ -4466,6 +4820,66 @@ dev = ["click (<8.3.0)", "cython-lint (>=0.12.2)", "mypy (==1.10.0)", "pycodesty doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)", "tabulate"] test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "scipy" +version = "1.18.0" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = ">=3.12" +groups = ["main"] +markers = "python_version >= \"3.12\"" +files = [ + {file = "scipy-1.18.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:7bd21faaf5a1a3b2eff922d02db5f191b99a6518db9078a8fb23169f6d22259a"}, + {file = "scipy-1.18.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:265915e79107de9f946b855e50d7470d5893ec3f54b342e1aa6201cbdcd8bb6b"}, + {file = "scipy-1.18.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9ab7b758be6940954a713ee466e2043e9f6e2ed965c1fce5c91039f4be3d90a9"}, + {file = "scipy-1.18.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:97b6cddaaee0a779ef6b5ca83c9604b27cc16b2b8fc22c142652df8793319fb8"}, + {file = "scipy-1.18.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:52a96e21517c7292375c0e27dd796a811f03fcea5fd4d108fdfea8145dcf17ab"}, + {file = "scipy-1.18.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f55797419e16e7f30cf88ffb3113ce0467f00cfe3f70d5c281730b21769bfc2"}, + {file = "scipy-1.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ad033410e2e0672ffdc1042110cef20e1c46f8fd0616cee1d44d8d58fad8fc11"}, + {file = "scipy-1.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a55985d54c769c872e64b7f4c8a81cc30ef700cc04296abbbf3705439c126de"}, + {file = "scipy-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:71ccc8faa2dd16ac310233203474a8b5cb67f10dedd54a3116d34943f4b19132"}, + {file = "scipy-1.18.0-cp312-cp312-win_arm64.whl", hash = "sha256:d88363fd9d8fbd3511bd273f1a49efb2a540773ddf92a91d57498ce7dd7f3e76"}, + {file = "scipy-1.18.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:09143f676d157d9f546d663504ef9c1becb819824f1afc018814176411942446"}, + {file = "scipy-1.18.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:5efe260f69417b97ddae455bfb5a95e8359f7f66ad7fa9522a60feb66f169520"}, + {file = "scipy-1.18.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:68363b7eaacd8b5dd426df56d782cc156468ac79a127a1b87ca597d6e2e82197"}, + {file = "scipy-1.18.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:c5557d8be5da8e41353fcd4d21491fdbab83b062fc579e94dc09a7c8ab4f669b"}, + {file = "scipy-1.18.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0d13bca67c096d89fb95ced0d8921807300fce0275643aef9533cc63a0773468"}, + {file = "scipy-1.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a46f9273dbd0eb1cefba61c9b8648b4dfe3cbc14a080176f9a73e44b8336dc7f"}, + {file = "scipy-1.18.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5aba46108853ddfc77906b6557aac839d2b52e900c1d72a1180adaaab58d265f"}, + {file = "scipy-1.18.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b6f758e35f12757b5d95c00bc6de2438e229c2664b7a92e96f205959d9f2dfa4"}, + {file = "scipy-1.18.0-cp313-cp313-win_amd64.whl", hash = "sha256:1afac4a847207c7ff8efd321734a50b06d0280b3b2a2c0fc2f413101747ad7c7"}, + {file = "scipy-1.18.0-cp313-cp313-win_arm64.whl", hash = "sha256:c5dbddf60e58c2312316d097271a8e73d40eaf2eabfa4d95ed7d3695bbf2ce7b"}, + {file = "scipy-1.18.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4c256ee70c0d1a8a2ace807e199ccd4e3f57037433842abb3fb36bc17eaa9578"}, + {file = "scipy-1.18.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:2ef3abc54a4ffc53765374b0d5728532dfdd2585ed23f6b11c206a1f0b1b9af8"}, + {file = "scipy-1.18.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2a6af57bd9e4a75d70e4117e78a1bbee84f79ae3fbb6d0111005d6ebcc4cb8d"}, + {file = "scipy-1.18.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:3f1ac564d3bf6c03d861d2cd87a1bea0da2887136f7fb1bf519c05a8971452d6"}, + {file = "scipy-1.18.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40395a5fcd1abee49a5c7aaa98c29db393eedc835138560a588c47ec16156690"}, + {file = "scipy-1.18.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ca01e8ae69f1b18e9a58d91afead31be3cef0dd905a10249dac559ee15460a0"}, + {file = "scipy-1.18.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7a7f3b01647384dbc3a711e8c6778e0aabbe93959249fef5c7393396bcac0867"}, + {file = "scipy-1.18.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6aa94e78ec192a30063a5e72e561c28af769dc311190b24fe91774eff1969709"}, + {file = "scipy-1.18.0-cp314-cp314-win_amd64.whl", hash = "sha256:2d8bbdc6c817f5b4006a54d799d4f5bab6f910193cbb9a1ff310833d4d270f61"}, + {file = "scipy-1.18.0-cp314-cp314-win_arm64.whl", hash = "sha256:18e9575f1569b2c54174e6159d32942e03731177f63dce7975f0a0c88d102f5b"}, + {file = "scipy-1.18.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f351e0dd702687d12a402b867a1b4146a256923e1c38317cbc472f6372b94707"}, + {file = "scipy-1.18.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7c7a51b33ce387193c97f228320cf8e87361daa1bba750638677729598b3e677"}, + {file = "scipy-1.18.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:84031d7b052a54fae2f8632e0ec802073d385476eb9a63079bce6e23ef9283d4"}, + {file = "scipy-1.18.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:56abf29a7c067dde59be8b9a22d606a4ea1b2f2a4b756d9d903c62818f5dacce"}, + {file = "scipy-1.18.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ad44305cfa24b1ba5803cbbebf033590ccbac1aa5d612d727b785325ab408b0"}, + {file = "scipy-1.18.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:945c1761b93f38d7f99ae81ae80c63e621471608c7eeead563f6df025585cd58"}, + {file = "scipy-1.18.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1a4441f15d620578772a49e5ab48c0ee1f7a0220e387110283062729136b2553"}, + {file = "scipy-1.18.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9aac6192fac56bf2ca534389d24623f07b39ff83317d58287285e7fbd622ff76"}, + {file = "scipy-1.18.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e40baea28ae7f5475c779741e2d90b1247c78531207b49c7030e698ff81cee3f"}, + {file = "scipy-1.18.0-cp314-cp314t-win_arm64.whl", hash = "sha256:368e0a705903c466aa5f08eefb39e6b1b6b2d659e7352a31fd9e2438365be0f8"}, + {file = "scipy-1.18.0.tar.gz", hash = "sha256:67b2ad2ad54c72ca6d04975a9b2df8c3638c34ddd5b28738e94fc2b57929d378"}, +] + +[package.dependencies] +numpy = ">=2.0.0,<2.8" + +[package.extras] +dev = ["click (<8.3.0)", "cython-lint (>=0.12.2)", "mypy (==1.19.1)", "pycodestyle", "pyrefly (==0.63.0)", "ruff (>=0.12.0)", "spin", "types-psutil", "typing_extensions"] +doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)", "tabulate"] +test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "scipy-doctest (>=2.0.0)", "threadpoolctl"] + [[package]] name = "seaborn" version = "0.13.2" @@ -4504,27 +4918,6 @@ files = [ nativelib = ["pyobjc (>=9.0) ; sys_platform == \"darwin\"", "pywin32 (>=305) ; sys_platform == \"win32\""] test = ["pytest (>=8)"] -[[package]] -name = "setuptools" -version = "82.0.1" -description = "Most extensible Python build backend with support for C/C++ extension modules" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb"}, - {file = "setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.13.0) ; sys_platform != \"cygwin\""] -core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.18.*)", "pytest-mypy"] - [[package]] name = "shapely" version = "2.1.2" @@ -4601,14 +4994,14 @@ test = ["pytest", "pytest-cov", "scipy-doctest"] [[package]] name = "simpy" -version = "4.1.1" +version = "4.1.2" description = "Event discrete, process based simulation for Python." optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "simpy-4.1.1-py3-none-any.whl", hash = "sha256:7c5ae380240fd2238671160e4830956f8055830a8317edf5c05e495b3823cd88"}, - {file = "simpy-4.1.1.tar.gz", hash = "sha256:06d0750a7884b11e0e8e20ce0bc7c6d4ed5f1743d456695340d13fdff95001a6"}, + {file = "simpy-4.1.2-py3-none-any.whl", hash = "sha256:43071f84b6512c9b4fcb33ef057f240ccb1d1f3b263f9b4f9229d072e310b372"}, + {file = "simpy-4.1.2.tar.gz", hash = "sha256:76ef36b71e0436ba94e55febc001c78879e493a323f045bbcfbb0b216e9b1fbc"}, ] [[package]] @@ -4637,14 +5030,14 @@ files = [ [[package]] name = "soupsieve" -version = "2.8.3" +version = "2.8.4" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95"}, - {file = "soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349"}, + {file = "soupsieve-2.8.4-py3-none-any.whl", hash = "sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65"}, + {file = "soupsieve-2.8.4.tar.gz", hash = "sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e"}, ] [[package]] @@ -4761,21 +5154,21 @@ files = [ [[package]] name = "tinycss2" -version = "1.4.0" +version = "1.5.1" description = "A tiny CSS parser" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"}, - {file = "tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"}, + {file = "tinycss2-1.5.1-py3-none-any.whl", hash = "sha256:3415ba0f5839c062696996998176c4a3751d18b7edaaeeb658c9ce21ec150661"}, + {file = "tinycss2-1.5.1.tar.gz", hash = "sha256:d339d2b616ba90ccce58da8495a78f46e55d4d25f9fd71dfd526f07e7d53f957"}, ] [package.dependencies] webencodings = ">=0.4" [package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] +doc = ["furo", "sphinx"] test = ["pytest", "ruff"] [[package]] @@ -4850,61 +5243,75 @@ files = [ [[package]] name = "tornado" -version = "6.5.5" +version = "6.5.7" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa"}, - {file = "tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521"}, - {file = "tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5"}, - {file = "tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07"}, - {file = "tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e"}, - {file = "tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca"}, - {file = "tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7"}, - {file = "tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b"}, - {file = "tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6"}, - {file = "tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9"}, + {file = "tornado-6.5.7-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:148b2eb15c2c765a50796172c1e499649b35f30d2e3c3d3e15913cfa56bfb163"}, + {file = "tornado-6.5.7-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9da38de27f1da3b78a966f0dae12b5a1ea9afe72ca805d84ff06508272ddf100"}, + {file = "tornado-6.5.7-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8d759e71906ee783f8867b93bf26a265743da4c1e2f4a018464c1ba019862972"}, + {file = "tornado-6.5.7-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a46347a18f23fb92b396beebe0fb78f61dda0cc302445202c16203d8a18848b"}, + {file = "tornado-6.5.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7778b30bef919231265e91c69963ce0f49a1e9c07ac900bbe75b19ce2575ba92"}, + {file = "tornado-6.5.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e726f0c75da7726eec023aa62751ff8878bd2737e34fbdd33b1ae5897d2200f5"}, + {file = "tornado-6.5.7-cp39-abi3-win32.whl", hash = "sha256:f8de3bf12d3efdd0cbe7c8887868198f8a91415e3f29fcf258d9b8eb7b1d9ae4"}, + {file = "tornado-6.5.7-cp39-abi3-win_amd64.whl", hash = "sha256:de942f843533a039ef9fa3d9c88c7cd8a7c94553fb5ad0154270989b3d99a2c4"}, + {file = "tornado-6.5.7-cp39-abi3-win_arm64.whl", hash = "sha256:ff934fce95643af5f11efdae618eaa73d469dc588641e5c8d19295a0c65c4796"}, + {file = "tornado-6.5.7.tar.gz", hash = "sha256:66c513a76cda70d53907bc27cf1447557699c2e95aa48ba27a442ff61c3ddfc2"}, ] [[package]] name = "tqdm" -version = "4.67.3" +version = "4.68.4" description = "Fast, Extensible Progress Meter" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["main", "examples"] files = [ - {file = "tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf"}, - {file = "tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb"}, + {file = "tqdm-4.68.4-py3-none-any.whl", hash = "sha256:5168118b2368f48c561afda8020fd79195b1bdb0bdf8086b88442c267a315dc2"}, + {file = "tqdm-4.68.4.tar.gz", hash = "sha256:19829c9673638f2a0b8617da4cdcb927e831cd88bcfcb6e78d42a4d1af131520"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] -discord = ["requests"] +discord = ["envwrap", "requests"] notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] +slack = ["envwrap", "slack-sdk"] +telegram = ["envwrap", "requests"] + +[[package]] +name = "tqdm-joblib" +version = "0.0.5" +description = "Tracking progress of joblib.Parallel execution" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "tqdm_joblib-0.0.5-py3-none-any.whl", hash = "sha256:5948fccca627970cc8340dd56ac49d29222ed110b9ee39fd310b76a1483b471f"}, + {file = "tqdm_joblib-0.0.5.tar.gz", hash = "sha256:34dd63c92e1b88b5118661a41eaf91001cac2687bfe217a4b6a9ab1bbf0f1c64"}, +] + +[package.dependencies] +tqdm = "*" [[package]] name = "traitlets" -version = "5.15.0" +version = "5.15.1" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "traitlets-5.15.0-py3-none-any.whl", hash = "sha256:fb36a18867a6803deab09f3c5e0fa81bb7b26a5c9e82501c9933f759166eff40"}, - {file = "traitlets-5.15.0.tar.gz", hash = "sha256:4fead733f81cf1c4c938e06f8ca4633896833c9d89eff878159457f4d4392971"}, + {file = "traitlets-5.15.1-py3-none-any.whl", hash = "sha256:770a53705f84b81ac107e83a1b3328ff2dae16094d8fc3cfc004e4b22dfd8e92"}, + {file = "traitlets-5.15.1.tar.gz", hash = "sha256:7b1c07854fe25acb39e009bae49f11b79ff6cbb2f27999104e9110e7a6b53722"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "mypy (>=1.7.0,<1.19) ; platform_python_implementation == \"PyPy\"", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.17.0,<1.19)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "typing-extensions" @@ -4920,19 +5327,20 @@ files = [ [[package]] name = "tzdata" -version = "2026.2" +version = "2026.3" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main", "dev"] files = [ - {file = "tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7"}, - {file = "tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10"}, + {file = "tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931"}, + {file = "tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415"}, ] +markers = {main = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version < \"3.11\""} [[package]] name = "unified-momentum-model" -version = "0.4.1" +version = "0.5.0" description = "" optional = false python-versions = "^3.8" @@ -4956,7 +5364,7 @@ figures = ["dualitic @ git+https://github.com/jaimeliew1/Dualitic.git", "ipykern type = "git" url = "https://github.com/Howland-Lab/Unified-Momentum-Model.git" reference = "HEAD" -resolved_reference = "e55945a541db1a88d70b34f408dbf26a772f1c2c" +resolved_reference = "1d515e60d3403a0a6160acbbc67430d70adea125" [[package]] name = "uri-template" @@ -4993,14 +5401,14 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "wcwidth" -version = "0.7.0" +version = "0.8.2" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2"}, - {file = "wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0"}, + {file = "wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85"}, + {file = "wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda"}, ] [[package]] @@ -5190,15 +5598,15 @@ viz = ["cartopy", "matplotlib", "nc-time-axis", "seaborn"] [[package]] name = "xarray" -version = "2026.4.0" +version = "2026.7.0" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.11" groups = ["main"] markers = "python_version >= \"3.11\"" files = [ - {file = "xarray-2026.4.0-py3-none-any.whl", hash = "sha256:d43751d9fb4a90f9249c30431684f00c41bc874f1edccd862631a40cbc0edf08"}, - {file = "xarray-2026.4.0.tar.gz", hash = "sha256:c4ac9a01a945d90d5b1628e2af045099a9d4943536d4f2ee3ae963c3b222d15b"}, + {file = "xarray-2026.7.0-py3-none-any.whl", hash = "sha256:bf9dd130b93806dc78e90c1b7ac24851b31557b888674c53622235691cf21824"}, + {file = "xarray-2026.7.0.tar.gz", hash = "sha256:361b495928fdbf5b58d0969bb6775339019da5e93ca74d61ddf4eb5edd6ce604"}, ] [package.dependencies] @@ -5218,4 +5626,4 @@ viz = ["cartopy (>=0.24)", "matplotlib (>=3.10)", "nc-time-axis", "seaborn"] [metadata] lock-version = "2.1" python-versions = ">3.10, <3.15" -content-hash = "06e1ae0fa2d7a9ffaef337f0c3f5bd81c913f6884ee640d925b8c206da6d7d4d" +content-hash = "aec736c656dc40fed742849be1fd4d9d6426518d6bc5ca1062dafdbb7b2cab23" diff --git a/pyproject.toml b/pyproject.toml index d01e8b4..5efce37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,8 @@ floris = {git = "https://github.com/misi9170/floris.git", branch = "feature/user rosco = "^2.10.4" ruamel-yaml = "^0.19.1" seaborn = "^0.13.2" +joblib = "^1.5.3" +tqdm-joblib = "^0.0.5" [tool.poetry.group.dev.dependencies] black = { extras = ["jupyter"], version = "^23.9.1" } From 12828f75799aea979c15976e474cd591319ef616 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 22 Jul 2026 11:05:39 -0400 Subject: [PATCH 28/50] Cleaned up interfaces --- MITRotor/BEMSolver.py | 5 +- MITRotor/FlorisInterface/FlorisInterface.py | 61 +-- MITRotor/FlorisInterface/ROSCOInterface.py | 401 ++++++-------------- MITRotor/Momentum.py | 6 +- examples/example_08_floris_rosco.py | 74 ++-- 5 files changed, 183 insertions(+), 364 deletions(-) diff --git a/MITRotor/BEMSolver.py b/MITRotor/BEMSolver.py index 2abe8b9..87f64d6 100644 --- a/MITRotor/BEMSolver.py +++ b/MITRotor/BEMSolver.py @@ -128,11 +128,8 @@ def Ctprime(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): Ctprime = self.Ct(grid="sector") / ((1 - self.a(grid="sector")) ** 2 * np.cos(eff_yaw) ** 2) return average(self.geom, Ctprime, grid=grid) - # TODO: make sure that this is correct!! Check with np.isclose(Cp, tsr * Cq) def Cq(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): - mu = np.asarray(self.geom.mu_mesh) - Ctau = self.Ctau_uncorr(grid="sector") - dCq = mu * Ctau + dCq = (self.geom.mu_mesh * self.Ctau_uncorr(grid="sector")) return average(self.geom, dCq, grid=grid) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index c035bd7..b720207 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -15,7 +15,7 @@ from MITRotor.Geometry import BEMGeometry from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM -from MITRotor.FlorisInterface.ROSCOInterface import query_controls_compat +from MITRotor.FlorisInterface.ROSCOInterface import query_controls from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw InterpLike = Union[interp1d, RegularGridInterpolator, Callable] @@ -28,7 +28,7 @@ def default_bem_factory(): geometry=BEMGeometry(Nr=10, Ntheta=20), tiploss_model=NoTipLoss() ) -# pitch vs windspeed interpolater if none provided by user +# default 1D pitch vs windspeed interpolater if none provided by user # for IEA 15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) def default_pitch_interp(): module_dir = os.path.dirname(__file__) @@ -39,7 +39,7 @@ def default_pitch_interp(): # TODO: should fill_value be extrapolate? return interp1d(wind_table, pitch_table, kind="linear", fill_value="extrapolate", bounds_error=False) -# tsr vs windspeed interpolater if none provided by user +# default 1D tsr vs windspeed interpolater if none provided by user # for IEA 15MW from figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) def default_tsr_interp(): module_dir = os.path.dirname(__file__) @@ -58,10 +58,14 @@ class MITRotorTurbine(BaseOperationModel): Args: bem_model (BEM): optional BEM model as defined in MITRotor, defaults to IEA15MW with UMM momentum model - pitch_interp (interp1d): optional 1D interpolator for pitch trajectory based on wind speed, - defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) + pitch_interp (interp1d): optional 1D or 2D interpolator for pitch trajectory based on wind speed, + if 1D by wind speed then yaw not accounted for, if 2D then wind speed and yaw accounted for. + Defaults to 1D IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf). + See ROSCOInterface.py for information on how to generate 2D control scheme interpolator. tsr_interp (interp1d): optional 1D interpolator for tsr trajectory based on wind speed, - defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf) + if 1D by wind speed then yaw not accounted for, if 2D then wind speed and yaw accounted for. + Defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf). + See ROSCOInterface.py for information on how to generate 2D control scheme interpolator. Methods: power @@ -73,21 +77,22 @@ class MITRotorTurbine(BaseOperationModel): gen_eff = field(init = True, default = 95.756, type=Optional[float]) # [%] eff_ratio = field(init=True, default=None, type=Optional[float]) # allow override - # TODO: figure out the default factory for the tsr and pitch!! Use saved file... # create interp objects based on pitch and tsr csvs - # pitch_interp = field(init = True, factory = default_pitch_interp, type = interp1d, repr = False) - pitch_interp = field(init=True, default=None, type=Optional[InterpLike], repr=False) + pitch_interp = field(init = True, factory = default_pitch_interp, type = Optional[InterpLike], repr = False) pitch_rad = field(init = True, default = True, type = bool) - # tsr_interp = field(init = True, factory = default_tsr_interp, type = interp1d, repr = False) - tsr_interp = field(init=True, default=None, type=Optional[InterpLike], repr=False) - rated_rotor_speed = field(init=True, default=None, type=Optional[float]) # [rad/s] + tsr_interp = field(init = True, factory = default_tsr_interp, type = Optional[InterpLike], repr=False) + rated_rotor_speed = field(init = True, default = None, type = Optional[float]) # [rad/s] # save most recent solution by unique floris arguments _last_key = field(init=False, default=None, type = bytes) _a = field(init=False, default=None, type = NDArrayFloat) _Ct = field(init=False, default=None, type = NDArrayFloat) + _u4 = field(init=False, default=None, type = NDArrayFloat) + _v4 = field(init=False, default=None, type = NDArrayFloat) + _w4 = field(init=False, default=None, type = NDArrayFloat) _power = field(init=False, default=None, type = NDArrayFloat) + # calculate a few needed fields post-initialization def __attrs_post_init__(self): if self.eff_ratio is None: gearbox_eff = self.bem_model.rotor.rosco_values[1] @@ -121,6 +126,9 @@ def _update_solution(self, self._last_key = key self._a = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._Ct = np.empty((n_findex, n_turbines), dtype=floris_float_type) + self._u4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) + self._v4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) + self._w4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._power = np.empty((n_findex, n_turbines), dtype=floris_float_type) # compute the power-effective wind speed across the rotor @@ -135,36 +143,29 @@ def _update_solution(self, # get setpoints yaw, tilt = np.deg2rad(yaw_angles), np.deg2rad(tilt_angles) eff_yaw = calc_eff_yaw(yaw, tilt) - # pitch = query_controls(self.pitch_interp, rotor_average_velocities, eff_yaw) - # tsr = query_controls(self.tsr_interp, rotor_average_velocities, eff_yaw) - pitch = query_controls_compat( + + pitch = query_controls( self.pitch_interp, rotor_average_velocities, eff_yaw, kind = "pitch" ) - tsr = query_controls_compat( + tsr = query_controls( self.tsr_interp, rotor_average_velocities, eff_yaw, kind = "tsr", rated_rotor_speed = self.rated_rotor_speed, rotor_radius = self.bem_model.rotor.R, ) - # pitch = self.pitch_interp(rotor_normal_average_velocities) if not self.pitch_rad: pitch = np.deg2rad(pitch) - # if self.rated_rotor_speed is None: - # tsr = self.tsr_interp(rotor_normal_average_velocities) - # else: - # R = self.bem_model.rotor.R - # tsr_lookup = self.tsr_interp(rotor_normal_average_velocities) - # omega_lookup = tsr_lookup * rotor_normal_average_velocities / R # rad/s implied by lookup - # tsr_from_rated_speed = self.rated_rotor_speed * R / rotor_average_velocities # above-rated branch - # tsr = np.where(omega_lookup <= self.rated_rotor_speed, tsr_lookup, tsr_from_rated_speed) - # tsr = np.maximum(tsr, 0.0) - + # solve BEM for setpoints from control curves for tindex in range(n_turbines): # solve BEM bem_sol = self.bem_model(pitch[:, tindex], tsr[:, tindex], yaw = yaw[:, tindex], tilt = tilt[:, tindex]) # get induction and thrust coeff self._a[:, tindex] = bem_sol.a() self._Ct[:, tindex] = bem_sol.Ct() - # compute power -> need generator efficiency + # get near wake velocities + self._u4 = bem_sol.u4, + self._v4 = bem_sol.v4 + self._w4 = bem_sol.w4 + # compute power self._power[:, tindex] = ( 0.5 * bem_sol.Cp() * air_density * rotor_area * (rotor_average_velocities[:, tindex])**3 @@ -184,4 +185,6 @@ def axial_induction(self, **kwargs) -> NDArrayFloat: self._update_solution(**kwargs) return self._a - # near_wake_velocities \ No newline at end of file + def near_wake_velocities(self, **kwargs) -> NDArrayFloat: + self._update_solution(**kwargs) + return (self._u4, self._v4, self._w4) \ No newline at end of file diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index de391fa..3ed1221 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -66,7 +66,7 @@ def load_from_mitrotor( turbine.J = turbine.rotor_inertia + turbine.generator_inertia * turbine.Ng**2 turbine.rated_torque = turbine.rated_power/(turbine.GenEff/100*turbine.rated_rotor_speed*turbine.Ng) - # Generate the look-up tables, mesh the grid and flatten the arrays for aerodynamic analysis + # Generate the look-up tables; mesh the grid and flatten the arrays for aerodynamic analysis TSR_initial = np.arange(0.5, 25., 0.5) pitch_initial = np.arange(0.0, 31., 1.0) pitch_initial_rad = np.deg2rad(pitch_initial) @@ -112,238 +112,6 @@ def load_from_mitrotor( # ----------------------------- # Generate control scheme # ----------------------------- -def _run_one_wind_row( - i, v, yaw_grid_rad, init_pitch_deg0, init_tsr0, - turbine_sim, bem, param_filename, dt, SimName -): - """ - Worker: solve all yaw points for a single wind speed index i. - Uses sequential warm-start across yaw in this row. - Returns row arrays (pitch/tsr/power), with NaN on fail/non-convergence. - """ - ny = len(yaw_grid_rad) - pitch_row = np.full(ny, np.nan, dtype=float) - tsr_row = np.full(ny, np.nan, dtype=float) - power_row = np.full(ny, np.nan, dtype=float) - - # Warm-start seeds for first yaw in this wind row - prev_pitch_deg = float(init_pitch_deg0) - prev_tsr = float(init_tsr0) - - for j, yaw_rad in enumerate(yaw_grid_rad): - controller_int = None - try: - init_omega = prev_tsr * v / turbine_sim.rotor_radius - init_gen = init_omega * turbine_sim.Ng - - controller_int = WarmStartControllerInterface( - lib_name, - param_filename=param_filename, - sim_name=f"{SimName}_{i}_{j}", - DT=dt, - init_ws=v, - init_rot_speed=init_omega, - init_gen_speed=init_gen, - init_pitch_deg=prev_pitch_deg, # deg - init_torque=0.0, - init_nac_imu=yaw_rad, # rad - ) - - # lightweight sim object compatible with sim_ws_mitrotor - sim = SimpleNamespace(turbine=turbine_sim, controller_int=controller_int) - - converged = sim_ws_mitrotor( - sim=sim, bem=bem, ws=v, dt=dt, - init_tsr=prev_tsr, - init_pitch=prev_pitch_deg, # deg - yaw_init=yaw_rad, # rad - wd=0.0, - verbose=False, - ) - - # Save only converged points; else remain NaN - if converged: - pitch_row[j] = sim.bld_pitch # rad - tsr_row[j] = sim.tsr - power_row[j] = sim.gen_power - - # update warm-start for next yaw - prev_pitch_deg = np.rad2deg(sim.bld_pitch) - prev_tsr = sim.tsr - - except Exception: - # leave NaN and continue to next yaw - if controller_int is not None: - try: - controller_int.kill_discon() - except Exception: - pass - continue - - return i, pitch_row, tsr_row, power_row - - -# def get_rosco_control_interps( -# rosco_yaml, bem, -# TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', SimName = "Sim1", -# GenEff = 95.756, generator_inertia = 1836784, -# regenerate = False, -# save_control_file = None, -# save_dir = ".", -# dt = 0.05, -# yaw_grid_deg = np.arange(0.0, 25.0, 1.0), # in degrees -# ): -# """ -# Creates pitch and tsr 2D interpolators using ROSCO controller tuning. - -# Creates turbine and controller. Controller is tuned on yaw = 0 Cp/Ct surfaces from MITRotor. -# ROSCO simulation with controller and turbrine is then run for each (wind_speed, yaw) combination -# till steady state. Steady-state set points are made into a 2D interpolator and optionally saved to -# a CSV. - -# Args: -# rosco_yaml (string): yaml file (+path) that defineds turbine and control parameters; -# [see MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml for example] -# bem (MITRotor.BEM): MITRotor BEM object -# TurbineName (string): string turbine name; default to "IEA15MW" -# GenEff (float): generator efficiency (0-100); defaults to IEA15MW value 95.756 -# generator_inertia (float): generator_inertia; defaults to IEA15MW value 1836784 [kg m^2] -# save_control_file (string): file name (+path) of saved look-up table value; if None (default) then not saved -# regenerate (bool): if True, then regenerate control path, else use saved in save_control_file; if save_control_file is None, set to True -# save_dir (string): path to save all files output when creating the interpolaters -# dt (float): timestep for ROSCO simulation; default = 0.05 seconds - -# Returns: -# pitch_interp (string): 1D pitch interpolator from wind speed tuned with ROSCO control paramters -# tsr_interp (string): 1D tsr interpolator from wind speed tuned with ROSCO control paramters -# rated_rotor_speed (float): rated rotor speed value -# """ - -# # load ROSCO inputs and make basic turbine -# inps = load_rosco_yaml(rosco_yaml) -# turbine_params = inps['turbine_params'] -# turbine = ROSCO_turbine.Turbine(turbine_params) - -# # if control csv exists and do not want to regenerate, load old csv -# if not regenerate and save_control_file is not None: -# pitch_interp, tsr_interp = load_control_interps_from_csv(save_control_file) -# return pitch_interp, tsr_interp, turbine.rated_rotor_speed - -# # load and check control parameters -# controller_params = inps['controller_params'] -# if controller_params["WE_Mode"] != 0: -# warnings.warn( -# "Using wind speed estimators in this simple simulation is known to cause problems. We suggest using WE_Mode = 0.", -# UserWarning, -# ) - -# # generate turbine Cp/Ct surfaces -# turbine = load_from_mitrotor( -# turbine, bem, -# TurbineName = TurbineName, rotor_performance_filename = rotor_performance_filename, -# generator_inertia = generator_inertia, GenEff = GenEff, -# yaw = 0.0, -# ) -# # save turbine Cp/Ct surface -# cp_filename = turbine.rotor_performance_filename -# write_rotor_performance(turbine, txt_filename=cp_filename) - -# # make and tune controller -# controller = ROSCO_controller.Controller(controller_params) -# controller.tune_controller(turbine) - -# # Write parameter input file -# param_filename = os.path.join(save_dir,'DISCON.IN') -# write_DISCON( -# turbine,controller, -# param_file=param_filename, -# txt_filename=cp_filename -# ) - -# # load initial setpoints from tuned controller -# init_pitch_list = np.rad2deg(np.maximum(controller.pitch_op, controller.ps_min_bld_pitch)) -# init_tsr_list = controller.TSR_op - -# # load/set values for interpolator axes -# v_grid = controller.v.copy() -# yaw_grid_deg = np.asarray(yaw_grid_deg, dtype=float) -# yaw_grid_rad = np.deg2rad(yaw_grid_deg) - -# pitch_tbl = np.zeros((len(v_grid), len(yaw_grid_rad))) -# tsr_tbl = np.zeros_like(pitch_tbl) -# power_tbl = np.zeros_like(pitch_tbl) - -# # needed constants -# R = turbine.rotor_radius -# GBRatio = turbine.Ng - -# # loop through interpolator axes and find setpoints using ROSCO simulation -# for (i, v) in enumerate(v_grid): -# # initial guess setpoints based on tuned controller -# init_pitch = init_pitch_list[i] -# init_tsr = init_tsr_list[i] -# init_omega = init_tsr * v / R -# init_gen = init_omega * GBRatio -# # loop through yaw -# for (j, yaw_rad) in enumerate(yaw_grid_rad): -# # create controller interface -# controller_int = WarmStartControllerInterface( -# lib_name, -# param_filename=param_filename, -# sim_name=f"{SimName}_{i}_{j}", -# DT=dt, -# init_ws=v, -# init_rot_speed=init_omega, -# init_gen_speed=init_gen, -# init_pitch_deg=init_pitch, # init_pitch is in deg -# init_torque=0.0, -# init_nac_imu=yaw_rad, # init_nac_imu is rad -# ) - -# # create the ROSCO simulation -# sim = ROSCO_sim.Sim(turbine, controller_int) -# # run the simulation to steady state -# sim_ws_mitrotor( -# sim=sim, bem=bem, ws=v, dt=dt, -# init_tsr=init_tsr, -# init_pitch=init_pitch, # deg -# yaw_init=yaw_rad, # rad -# wd=0.0, -# ) -# # save setpoints in 2D tables -# pitch_tbl[i, j] = sim.bld_pitch -# tsr_tbl[i, j] = sim.tsr -# power_tbl[i, j] = sim.gen_power - -# # save CSV of (optional) -# if save_control_file is not None: -# save_control_file = Path(save_control_file) -# save_control_file.parent.mkdir(parents=True, exist_ok=True) - -# vv, yy = np.meshgrid(v_grid, yaw_grid_rad, indexing="ij") -# data = np.column_stack([ -# vv.ravel(), # wind_speed_mps -# yy.ravel(), # yaw_rad -# pitch_tbl.ravel(), # pitch_rad -# tsr_tbl.ravel(), # tsr -# power_tbl.ravel(), # generated power -# ]) - -# header = "wind_speed_mps,yaw_rad,pitch_rad,tsr,gen_power" -# np.savetxt(save_control_file, data, delimiter=",", header=header, comments="") - -# # Direct 2D interpolators, no custom wrapper -# pitch_interp = RegularGridInterpolator( -# (v_grid, yaw_grid_rad), pitch_tbl, -# method="linear", bounds_error=False, fill_value=None -# ) -# tsr_interp = RegularGridInterpolator( -# (v_grid, yaw_grid_rad), tsr_tbl, -# method="linear", bounds_error=False, fill_value=None -# ) - -# return pitch_interp, tsr_interp, turbine.rated_rotor_speed - def get_rosco_control_interps( rosco_yaml, bem, TurbineName="IEA15MW", rotor_performance_filename='Cp_Ct_Cq.txt', SimName="Sim1", @@ -361,26 +129,25 @@ def get_rosco_control_interps( in one worker with warm-start chaining. """ - # load ROSCO inputs and make basic turbine + # Load ROSCO inputs and make basic turbine inps = load_rosco_yaml(rosco_yaml) turbine_params = inps['turbine_params'] turbine = ROSCO_turbine.Turbine(turbine_params) - # if control csv exists and do not want to regenerate, load old csv + # If control csv exists and do not want to regenerate, load old csv if not regenerate and save_control_file is not None: pitch_interp, tsr_interp = load_control_interps_from_csv(save_control_file) return pitch_interp, tsr_interp, turbine.rated_rotor_speed - # load and check control parameters + # Load and check control parameters controller_params = inps['controller_params'] - if controller_params["WE_Mode"] != 0: + if (controller_params["WE_Mode"] != 0) or (controller_params["WE_Mode"] != 2): warnings.warn( - "Using wind speed estimators in this simple simulation is known to cause problems. " - "We suggest using WE_Mode = 0.", + "We suggest using WE_Mode = 0 or WE_Mode = 2 within the control parameter file.", UserWarning, ) - # generate turbine Cp/Ct surfaces + # Generate turbine Cp/Ct surfaces turbine = load_from_mitrotor( turbine, bem, TurbineName=TurbineName, rotor_performance_filename=rotor_performance_filename, @@ -388,11 +155,11 @@ def get_rosco_control_interps( yaw=0.0, ) - # save turbine Cp/Ct surface + # Save turbine Cp/Ct surface cp_filename = turbine.rotor_performance_filename write_rotor_performance(turbine, txt_filename=cp_filename) - # make and tune controller + # Make and tune controller controller = ROSCO_controller.Controller(controller_params) controller.tune_controller(turbine) @@ -404,11 +171,11 @@ def get_rosco_control_interps( txt_filename=cp_filename ) - # tuned initial setpoints + # Tuned initial setpoints init_pitch_list = np.rad2deg(np.maximum(controller.pitch_op, controller.ps_min_bld_pitch)) init_tsr_list = controller.TSR_op - # axes + # Create parameter tables v_grid = controller.v.copy() yaw_grid_deg = np.sort(np.asarray(yaw_grid_deg, dtype=float)) yaw_grid_rad = np.deg2rad(yaw_grid_deg) @@ -417,7 +184,7 @@ def get_rosco_control_interps( tsr_tbl = np.full_like(pitch_tbl, np.nan) power_tbl = np.full_like(pitch_tbl, np.nan) - # lightweight turbine object for worker pickling + # Lightweight turbine object for worker pickling turbine_sim = SimpleNamespace( rotor_radius=float(turbine.rotor_radius), rho=float(turbine.rho), @@ -427,11 +194,12 @@ def get_rosco_control_interps( GenEff=float(turbine.GenEff), ) + # Calculate total number of cases n_wind = len(v_grid) n_yaw = len(yaw_grid_rad) total_cases = n_wind * n_yaw - # determine effective n_jobs + # Determine effective n_jobs if n_jobs is None: n_jobs_eff = 1 elif n_jobs == -1: @@ -439,7 +207,7 @@ def get_rosco_control_interps( else: n_jobs_eff = max(1, min(int(n_jobs), n_wind)) - # run parallel (fallback to serial on failure, e.g., pickling issue) + # Run parallel (fallback to serial on failure, e.g., pickling issue) print( f"Starting control LUT sweep: {n_wind} wind-row tasks " f"({total_cases} wind-yaw cases), using {n_jobs_eff} worker process(es)." @@ -480,13 +248,13 @@ def _run_serial(desc): desc = "Control LUT sweep (serial fallback)" if n_jobs_eff > 1 else "Control LUT sweep (serial)" rows = _run_serial(desc) - # collect + # Collect setpoints for i, pitch_row, tsr_row, power_row in rows: pitch_tbl[i, :] = pitch_row tsr_tbl[i, :] = tsr_row power_tbl[i, :] = power_row - # optional CSV save + # Optional CSV save if save_control_file is not None: save_control_file = Path(save_control_file) save_control_file.parent.mkdir(parents=True, exist_ok=True) @@ -503,7 +271,7 @@ def _run_serial(desc): header = "wind_speed_mps,yaw_rad,pitch_rad,tsr,gen_power" np.savetxt(save_control_file, data, delimiter=",", header=header, comments="") - # interpolators + # Make interpolators pitch_interp = RegularGridInterpolator( (v_grid, yaw_grid_rad), pitch_tbl, method="linear", bounds_error=False, fill_value=None @@ -515,6 +283,76 @@ def _run_serial(desc): return pitch_interp, tsr_interp, turbine.rated_rotor_speed +def _run_one_wind_row( + i, v, yaw_grid_rad, init_pitch_deg0, init_tsr0, + turbine_sim, bem, param_filename, dt, SimName +): + """ + Worker: solve all yaw points for a single wind speed index i. + Uses sequential warm-start across yaw in this row. + Returns row arrays (pitch/tsr/power), with NaN on fail/non-convergence. + """ + ny = len(yaw_grid_rad) + pitch_row = np.full(ny, np.nan, dtype=float) + tsr_row = np.full(ny, np.nan, dtype=float) + power_row = np.full(ny, np.nan, dtype=float) + + # Warm-start seeds for first yaw in this wind row + prev_pitch_deg = float(init_pitch_deg0) + prev_tsr = float(init_tsr0) + + for j, yaw_rad in enumerate(yaw_grid_rad): + controller_int = None + try: + init_omega = prev_tsr * v / turbine_sim.rotor_radius + init_gen = init_omega * turbine_sim.Ng + + controller_int = WarmStartControllerInterface( + lib_name, + param_filename=param_filename, + sim_name=f"{SimName}_{i}_{j}", + DT=dt, + init_ws=v, + init_rot_speed=init_omega, + init_gen_speed=init_gen, + init_pitch_deg=prev_pitch_deg, # deg + init_torque=0.0, + init_nac_imu=yaw_rad, # rad + ) + + # lightweight sim object compatible with sim_ws_mitrotor + sim = SimpleNamespace(turbine=turbine_sim, controller_int=controller_int) + + converged = sim_ws_mitrotor( + sim=sim, bem=bem, ws=v, dt=dt, + init_tsr=prev_tsr, + init_pitch=prev_pitch_deg, # deg + yaw_init=yaw_rad, # rad + wd=0.0, + verbose=False, + ) + + # Save only converged points; else remain NaN + if converged: + pitch_row[j] = sim.bld_pitch # rad + tsr_row[j] = sim.tsr + power_row[j] = sim.gen_power + + # update warm-start for next yaw + prev_pitch_deg = np.rad2deg(sim.bld_pitch) + prev_tsr = sim.tsr + + except Exception: + # leave NaN and continue to next yaw + if controller_int is not None: + try: + controller_int.kill_discon() + except Exception: + pass + continue + + return i, pitch_row, tsr_row, power_row + def load_control_interps_from_csv(csv_path): """ @@ -552,32 +390,7 @@ def load_control_interps_from_csv(csv_path): return pitch_interp, tsr_interp -# def query_controls(interp, ws, yaw_rad): -# """ -# Vectorized query for 2D interpolator interp(ws, yaw). - -# Supports: -# - scalar ws, scalar yaw -> float -# - array ws, scalar yaw -> array -# - scalar ws, array yaw -> array -# - array ws, array yaw (broadcastable shapes, including same-length 1D pairwise) -> array -# """ -# ws_arr = np.asarray(ws, dtype=float) -# yaw_arr = np.asarray(yaw_rad, dtype=float) - -# # Broadcast to common shape (or raise if incompatible) -# ws_b, yaw_b = np.broadcast_arrays(ws_arr, yaw_arr) - -# # Build points for RegularGridInterpolator: shape (N, 2) -# pts = np.column_stack((ws_b.ravel(), yaw_b.ravel())) - -# # Vectorized interpolation -# vals = np.asarray(interp(pts)).reshape(ws_b.shape) - -# # Return float for scalar input, ndarray otherwise -# return float(vals) if vals.shape == () else vals - -def query_controls_compat( +def query_controls( interp, ws, yaw_rad, @@ -667,14 +480,11 @@ def sim_ws_mitrotor( t = 0.0 converged = False last_metrics = None - # begin iteration + # Begin iteration while n_iter < max_iter: t += dt - # aero side tsr = rot_speed * R / max(ws, 1e-6) - - # yaw misalignment for aero yaw_err = wd - nac_yaw # BEM call @@ -685,7 +495,7 @@ def sim_ws_mitrotor( ) cp = float(np.ravel(sol.Cp())[0]) - # 1DOF rotor dynamics (same structure as ROSCO Sim) + # Rotor dynamics calculations (same as used in ROSCO's sim_ws_series function) aero_torque = 0.5 * rho * (np.pi * R**3) * (cp / max(tsr, 1e-6)) * ws**2 rot_speed = rot_speed + (dt / J) * (aero_torque - Ng * gen_torque / gbox_eff) gen_speed = rot_speed * Ng @@ -705,13 +515,13 @@ def sim_ws_mitrotor( "Y_MeasErr": yaw_err, } - # Controller outputs + # Controller call; torque, blade pitch, and yaw rate outputs gen_torque, bld_pitch, nac_yawrate = sim.controller_int.call_controller(turbine_state) - # Power + # Calculate power gen_power = gen_speed * gen_torque * gen_eff # W - # Yaw dynamics + # Yaw dynamics update for if yaw-control is on nac_yaw += nac_yawrate * dt # Convergence tracking @@ -737,6 +547,7 @@ def sim_ws_mitrotor( if not converged and verbose: print(f"WARNING: hit max_iter={max_iter} without convergence") + # Kill controller sim.controller_int.kill_discon() @@ -753,7 +564,9 @@ def sim_ws_mitrotor( return converged - +# ----------------------------- +# Controller Interface -> child of ROSCOS's ControllerInterface +# ----------------------------- class WarmStartControllerInterface(ROSCO_ci.ControllerInterface): """ ROSCO controller interface with configurable warm-start initial conditions. @@ -807,13 +620,14 @@ def __init__( Additional keyword arguments forwarded to `ROSCO_ci.ControllerInterface` (e.g., `DT`, `sim_name`, etc.). """ + # Set starting conditions self.init_ws = float(init_ws) self.init_rot_speed = float(init_rot_speed) self.init_gen_speed = float(init_gen_speed) self.init_torque = float(init_torque) self.init_nac_imu = float(init_nac_imu) - # parent uses self.pitch for initial blade pitch + # Parent uses self.pitch for initial blade pitch super().__init__( lib_name, param_filename=param_filename, @@ -880,25 +694,30 @@ def init_discon(self): self.avrSWAP[50] = len(self.avcOUTNAME) self.avrSWAP[51] = self.char_buffer - with suppress_c_output(): + with suppress_fortran_output(): self.call_discon() # iStatus=0 init call self.avrSWAP[0] = 1 # subsequent calls are normal if self.aviFAIL.value < 0: raise ValueError("ROSCO dynamic library has returned an error") + def kill_discon(self): - """Silent DISCON shutdown (suppresses ROSCO shutdown print spam).""" + """ + Silent DISCON shutdown (suppresses ROSCO shutdown print spam). + Removes ROSCO FORTRAN output clean up terminal so MITRotor interface + outputs are visible. + """ try: - with suppress_c_output(): # the context manager you already added + with suppress_fortran_output(): # context manager super().kill_discon() except Exception: pass @contextmanager -def suppress_c_output(): - """Suppress C/Fortran prints (stdout/stderr) in this process.""" +def suppress_fortran_output(): + """Suppress Fortran prints (stdout/stderr) in this process.""" sys.stdout.flush() sys.stderr.flush() diff --git a/MITRotor/Momentum.py b/MITRotor/Momentum.py index 6834ff0..2f114ff 100644 --- a/MITRotor/Momentum.py +++ b/MITRotor/Momentum.py @@ -281,7 +281,7 @@ def __init__(self, averaging: Literal["sector", "annulus", "rotor"] = "rotor", b self.model_Ct = ( model_Ct if model_Ct is not None - else UMM.ThrustBasedUnified(beta=beta) + else UMM.ThrustBasedUnified(beta_s=beta) ) def compute_induction(self, Cx: ArrayLike, yaw: float = 0.0, tilt: float = 0.0) -> ArrayLike: @@ -296,7 +296,7 @@ def compute_initial_wake_velocities(self, Cx: ArrayLike, yaw: float = 0.0, tilt: # Look-up table for unified model def func_Ct(x, beta, cached) -> dict: Ct, eff_yaw = x - model_Ct = UMM.ThrustBasedUnified(beta = beta, cached=cached) + model_Ct = UMM.ThrustBasedUnified(beta_s = beta, cached=cached) sol = model_Ct(Ct, np.deg2rad(np.round(eff_yaw, 2))) return dict( Ct=Ct, @@ -330,7 +330,7 @@ class ThrustBasedUnifiedLUT(CachedLUT, UMM.MomentumBase): as described in UMM documentation, yaw and tilt can be combined into an "effective yaw" the cache uses effective yaw, so these values should cover the range of effective yaws you want. You can use UnifiedMomentumModel.Utilities.Geometry.calc_eff_yaw to find - - beta (float, optional) - used in UMM + - beta_s (float, optional) - used in UMM - cached (boolean, optional) - cache nonlinear pressure in UMM """ def __init__(self, cache_fn: Path = CACHE_FN_CT, regenerate=False, s=0.025, diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 30035fb..5b68155 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -22,7 +22,7 @@ from MITRotor.Momentum import UnifiedMomentumLUT from MITRotor import BEM, BEMGeometry, IEA15MW from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp -from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls_compat +from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls figdir = Path("fig") @@ -78,7 +78,7 @@ def main(): cache_file = cache_dir / "lut.csv" lut_model = UnifiedMomentumLUT( cache_fn=cache_file, - regenerate=False, + regenerate=True, LUT_Cts=np.linspace(-0.5,1.5,40), LUT_yaws=np.linspace(0.0,40.0,40), ) @@ -95,25 +95,25 @@ def main(): end = time.time() print(f"Time to make control CSV: {end - start}") - rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param( - "PS_Mode", 0, rosco_yaml_PS_Mode_3, bem, - regenerate = True, save_control_file = "control_PS0.csv" - ) + # rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param( + # "PS_Mode", 0, rosco_yaml_PS_Mode_3, bem, + # regenerate = True, save_control_file = "control_PS0.csv" + # ) # Plot IEA15MW control from ROSCO paper, ROSOC control with PS_Mode = 3, and ROSOC control with PS_Mode = 0 pitch_abbas = abbas_pitch_interp(wind_speeds) - pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) - pitch_ps3 = np.rad2deg(query_controls_compat(rosco_PS_Mode_3_pitch_interp, wind_speeds, 0.0)) + # pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) + pitch_ps3 = np.rad2deg(query_controls(rosco_PS_Mode_3_pitch_interp, wind_speeds, 0.0)) tsr_abbas = abbas_tsr_interp(wind_speeds) - tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) - tsr_ps3 = query_controls_compat(rosco_PS_Mode_3_tsr_interp, wind_speeds, 0.0) + # tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) + tsr_ps3 = query_controls(rosco_PS_Mode_3_tsr_interp, wind_speeds, 0.0) # Create figure fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) fig.suptitle(fr"Setpoint Trajectories") # Plot pitch - ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) + # ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") @@ -123,7 +123,7 @@ def main(): ax[0].grid(True) # Plot TSR - ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) + # ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") @@ -147,13 +147,13 @@ def main(): tsr_interp = abbas_tsr_interp, ) - floris_PS_Mode_0_turbine = MITRotorTurbine( - bem_model = bem, - pitch_interp = rosco_PS_Mode_0_pitch_interp, - pitch_rad = True, - tsr_interp = rosco_PS_Mode_0_tsr_interp, - rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, - ) + # floris_PS_Mode_0_turbine = MITRotorTurbine( + # bem_model = bem, + # pitch_interp = rosco_PS_Mode_0_pitch_interp, + # pitch_rad = True, + # tsr_interp = rosco_PS_Mode_0_tsr_interp, + # rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, + # ) floris_PS_Mode_3_turbine = MITRotorTurbine( bem_model = bem, @@ -178,12 +178,12 @@ def main(): Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) - fmodel_PS_Mode_0 = FlorisModel("defaults") - fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) - fmodel_PS_Mode_0.run() - Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() - Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) + # fmodel_PS_Mode_0 = FlorisModel("defaults") + # fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + # fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) + # fmodel_PS_Mode_0.run() + # Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() + # Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) fmodel_PS_Mode_3 = FlorisModel("defaults") fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) @@ -203,10 +203,10 @@ def main(): wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", lw=3, linestyle = "solid", zorder = 1, ) - ax1.plot( - wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", - lw=3, linestyle = "dashed", zorder = 1, - ) + # ax1.plot( + # wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", + # lw=3, linestyle = "dashed", zorder = 1, + # ) ax1.plot(wind_speeds, Ct_PS_Mode_3, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -224,10 +224,10 @@ def main(): wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "solid", zorder = 1, ) - ax2.plot( - wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - lw=3, linestyle = "dashed", zorder = 1, - ) + # ax2.plot( + # wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + # lw=3, linestyle = "dashed", zorder = 1, + # ) ax2.plot(wind_speeds, Cp_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -245,10 +245,10 @@ def main(): wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "solid", zorder = 1, ) - ax3.plot( - wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - lw=3, linestyle = "dashed", zorder = 1, - ) + # ax3.plot( + # wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + # lw=3, linestyle = "dashed", zorder = 1, + # ) ax3.plot(wind_speeds, P_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) From f4b8be41c0cfb80783f81441bbe755b51af15b9b Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 29 Jul 2026 11:52:19 -0400 Subject: [PATCH 29/50] Updated for final cleanups --- MITRotor/FlorisInterface/ROSCOInterface.py | 90 ++++++++++++---------- examples/example_08_floris_rosco.py | 79 ++++++++++--------- 2 files changed, 93 insertions(+), 76 deletions(-) diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 3ed1221..93050d9 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -22,6 +22,7 @@ from rosco.toolbox import sim as ROSCO_sim from rosco.toolbox.utilities import write_rotor_performance, write_DISCON from rosco.toolbox.inputs.validation import load_rosco_yaml +import time # ----------------------------- # Create Ct/Cp surfaces @@ -107,6 +108,10 @@ def load_from_mitrotor( turbine.Cp = ROSCO_turbine.RotorPerformance(turbine.Cp_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) turbine.Ct = ROSCO_turbine.RotorPerformance(turbine.Ct_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) turbine.Cq = ROSCO_turbine.RotorPerformance(turbine.Cq_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) + + if not turbine.TSR_operational: # TODO: make it clear that this is reccomeneded! + turbine.TSR_operational = turbine.Cp.TSR_opt + return turbine # ----------------------------- @@ -141,7 +146,7 @@ def get_rosco_control_interps( # Load and check control parameters controller_params = inps['controller_params'] - if (controller_params["WE_Mode"] != 0) or (controller_params["WE_Mode"] != 2): + if (controller_params["WE_Mode"] != 0) and (controller_params["WE_Mode"] != 2): warnings.warn( "We suggest using WE_Mode = 0 or WE_Mode = 2 within the control parameter file.", UserWarning, @@ -177,6 +182,7 @@ def get_rosco_control_interps( # Create parameter tables v_grid = controller.v.copy() + # v_grid = np.flip(v_grid) yaw_grid_deg = np.sort(np.asarray(yaw_grid_deg, dtype=float)) yaw_grid_rad = np.deg2rad(yaw_grid_deg) @@ -209,32 +215,32 @@ def get_rosco_control_interps( # Run parallel (fallback to serial on failure, e.g., pickling issue) print( - f"Starting control LUT sweep: {n_wind} wind-row tasks " + f"Starting control LUT sweep: {n_yaw} yaw tasks " f"({total_cases} wind-yaw cases), using {n_jobs_eff} worker process(es)." ) def _run_serial(desc): out = [] - for i, v in enumerate(tqdm(v_grid, total=n_wind, desc=desc, dynamic_ncols=True)): + for i, yaw_rad in enumerate(tqdm(yaw_grid_rad, total=n_wind, desc=desc, dynamic_ncols=True)): out.append( _run_one_wind_row( - i, v, yaw_grid_rad, init_pitch_list[i], init_tsr_list[i], + i, v_grid, yaw_rad, init_pitch_list, init_tsr_list, turbine_sim, bem, param_filename, dt, SimName ) ) return out - rows = None + cols = None if n_jobs_eff > 1: - bar = tqdm(total=n_wind, desc="Control LUT sweep (wind rows)", dynamic_ncols=True) + bar = tqdm(total=n_yaw, desc="Control LUT sweep (wind cols)", dynamic_ncols=True) try: with tqdm_joblib(bar): - rows = Parallel(n_jobs=n_jobs_eff, backend="loky", verbose=0, batch_size=1)( + cols = Parallel(n_jobs=n_jobs_eff, backend="loky", verbose=0, batch_size=1)( delayed(_run_one_wind_row)( - i, v, yaw_grid_rad, init_pitch_list[i], init_tsr_list[i], + i, v_grid, yaw_rad, init_pitch_list, init_tsr_list, turbine_sim, bem, param_filename, dt, SimName ) - for i, v in enumerate(v_grid) + for i, yaw_rad in enumerate(yaw_grid_rad) ) except Exception as e: warnings.warn( @@ -244,15 +250,15 @@ def _run_serial(desc): ) finally: bar.close() - if rows is None: + if cols is None: desc = "Control LUT sweep (serial fallback)" if n_jobs_eff > 1 else "Control LUT sweep (serial)" - rows = _run_serial(desc) + cols = _run_serial(desc) # Collect setpoints - for i, pitch_row, tsr_row, power_row in rows: - pitch_tbl[i, :] = pitch_row - tsr_tbl[i, :] = tsr_row - power_tbl[i, :] = power_row + for i, pitch_col, tsr_col, power_col in cols: + pitch_tbl[:, i] = pitch_col + tsr_tbl[:, i] = tsr_col + power_tbl[:, i] = power_col # Optional CSV save if save_control_file is not None: @@ -284,7 +290,7 @@ def _run_serial(desc): return pitch_interp, tsr_interp, turbine.rated_rotor_speed def _run_one_wind_row( - i, v, yaw_grid_rad, init_pitch_deg0, init_tsr0, + i, v_grid, yaw_rad, init_pitch_deg_list, init_tsr_list, turbine_sim, bem, param_filename, dt, SimName ): """ @@ -292,19 +298,21 @@ def _run_one_wind_row( Uses sequential warm-start across yaw in this row. Returns row arrays (pitch/tsr/power), with NaN on fail/non-convergence. """ - ny = len(yaw_grid_rad) - pitch_row = np.full(ny, np.nan, dtype=float) - tsr_row = np.full(ny, np.nan, dtype=float) - power_row = np.full(ny, np.nan, dtype=float) + nv = len(v_grid) + pitch_col = np.full(nv, np.nan, dtype=float) + tsr_col = np.full(nv, np.nan, dtype=float) + power_col = np.full(nv, np.nan, dtype=float) # Warm-start seeds for first yaw in this wind row - prev_pitch_deg = float(init_pitch_deg0) - prev_tsr = float(init_tsr0) + # prev_pitch_deg = float(init_pitch_deg0) + # prev_tsr = float(init_tsr0) - for j, yaw_rad in enumerate(yaw_grid_rad): + for j, v in enumerate(v_grid): controller_int = None try: - init_omega = prev_tsr * v / turbine_sim.rotor_radius + init_pitch_deg = init_pitch_deg_list[j] + init_tsr = init_tsr_list[j] + init_omega = init_tsr * v / turbine_sim.rotor_radius init_gen = init_omega * turbine_sim.Ng controller_int = WarmStartControllerInterface( @@ -315,7 +323,7 @@ def _run_one_wind_row( init_ws=v, init_rot_speed=init_omega, init_gen_speed=init_gen, - init_pitch_deg=prev_pitch_deg, # deg + init_pitch_deg=init_pitch_deg, # deg init_torque=0.0, init_nac_imu=yaw_rad, # rad ) @@ -325,8 +333,8 @@ def _run_one_wind_row( converged = sim_ws_mitrotor( sim=sim, bem=bem, ws=v, dt=dt, - init_tsr=prev_tsr, - init_pitch=prev_pitch_deg, # deg + init_tsr=init_tsr, + init_pitch=init_pitch_deg, # deg yaw_init=yaw_rad, # rad wd=0.0, verbose=False, @@ -334,13 +342,9 @@ def _run_one_wind_row( # Save only converged points; else remain NaN if converged: - pitch_row[j] = sim.bld_pitch # rad - tsr_row[j] = sim.tsr - power_row[j] = sim.gen_power - - # update warm-start for next yaw - prev_pitch_deg = np.rad2deg(sim.bld_pitch) - prev_tsr = sim.tsr + pitch_col[j] = sim.bld_pitch # rad + tsr_col[j] = sim.tsr + power_col[j] = sim.gen_power except Exception: # leave NaN and continue to next yaw @@ -351,7 +355,7 @@ def _run_one_wind_row( pass continue - return i, pitch_row, tsr_row, power_row + return i, pitch_col, tsr_col, power_col def load_control_interps_from_csv(csv_path): @@ -371,7 +375,7 @@ def load_control_interps_from_csv(csv_path): v_grid = np.unique(ws) yaw_grid = np.unique(yaw) - # sort rows by (ws, yaw), then reshape into [n_ws, n_yaw] + # sort cols by (ws, yaw), then reshape into [n_ws, n_yaw] order = np.lexsort((yaw, ws)) n_ws, n_yaw = len(v_grid), len(yaw_grid) @@ -481,18 +485,22 @@ def sim_ws_mitrotor( converged = False last_metrics = None # Begin iteration + t = 0.0 while n_iter < max_iter: t += dt - tsr = rot_speed * R / max(ws, 1e-6) + tsr = rot_speed * R / max(ws, 1e-6) yaw_err = wd - nac_yaw # BEM call + start = time.time() sol = bem( bld_pitch, tsr, yaw = yaw_err, - tilt = 0.0 + tilt = 0.0 # TODO: add in tilt ) + end = time.time() + t += (end - start) cp = float(np.ravel(sol.Cp())[0]) # Rotor dynamics calculations (same as used in ROSCO's sim_ws_series function) @@ -553,7 +561,7 @@ def sim_ws_mitrotor( # Save outputs sim.bld_pitch = bld_pitch # rad - sim.tsr = rot_speed * R / max(ws, 1e-6) + sim.tsr = rot_speed * R / max(ws, 1e-6) # TSR w.r.t. freestream sim.rot_speed = rot_speed # rad/s sim.gen_speed = gen_speed # rad/s sim.gen_torque = gen_torque # Nm @@ -562,6 +570,8 @@ def sim_ws_mitrotor( sim.n_iter = n_iter sim.converged = converged + print(ws, yaw_init, sim.bld_pitch, sim.tsr, t / n_iter) + return converged # ----------------------------- @@ -763,7 +773,7 @@ class ConvergenceSettings: window_time: float = 20.0 hold_time: float = 5.0 tol_rel_power_std: float = 1e-3 - tol_domega_dt: float = 1e-4 + tol_domega_dt: float = 1e-3 tol_dpitch_dt: float = np.deg2rad(1e-3) diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 5b68155..3e15483 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -24,6 +24,10 @@ from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls + + + + figdir = Path("fig") def change_control_param(param_key, param_value, template_yaml, bem, regenerate = False, save_control_file = "control.csv"): @@ -42,6 +46,7 @@ def change_control_param(param_key, param_value, template_yaml, bem, regenerate pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( temp_yaml, bem, regenerate = regenerate, save_control_file = save_control_file, + # n_jobs=1 ) return pitch_interp, tsr_interp, rated_rotor_speed @@ -78,7 +83,7 @@ def main(): cache_file = cache_dir / "lut.csv" lut_model = UnifiedMomentumLUT( cache_fn=cache_file, - regenerate=True, + regenerate=False, LUT_Cts=np.linspace(-0.5,1.5,40), LUT_yaws=np.linspace(0.0,40.0,40), ) @@ -88,32 +93,34 @@ def main(): # Load IEA15MW ROSCO parameters to make controllers start = time.time() rosco_yaml_PS_Mode_3 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" + # takes ~25min with 8 workers rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp, rosco_PS_Mode_3_rated_rotorspeed = get_rosco_control_interps( rosco_yaml_PS_Mode_3, bem, - # regenerate = False, save_control_file = "control.csv") - regenerate = True, save_control_file = "control.csv") + # regenerate = False, save_control_file = "control_ps_3.csv") + regenerate = True, save_control_file = "control_ps_3.csv") end = time.time() print(f"Time to make control CSV: {end - start}") - # rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param( - # "PS_Mode", 0, rosco_yaml_PS_Mode_3, bem, - # regenerate = True, save_control_file = "control_PS0.csv" - # ) + rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param( + "PS_Mode", 0, rosco_yaml_PS_Mode_3, bem, + # regenerate = True, save_control_file = "control_ps_0.csv", + regenerate = False, save_control_file = "control_ps_0.csv" + ) # Plot IEA15MW control from ROSCO paper, ROSOC control with PS_Mode = 3, and ROSOC control with PS_Mode = 0 pitch_abbas = abbas_pitch_interp(wind_speeds) - # pitch_ps0 = np.rad2deg(rosco_PS_Mode_0_pitch_interp(wind_speeds)) + pitch_ps0 = np.rad2deg(query_controls(rosco_PS_Mode_0_pitch_interp, wind_speeds, 0.0)) pitch_ps3 = np.rad2deg(query_controls(rosco_PS_Mode_3_pitch_interp, wind_speeds, 0.0)) tsr_abbas = abbas_tsr_interp(wind_speeds) - # tsr_ps0 = rosco_PS_Mode_0_tsr_interp(wind_speeds) + tsr_ps0 = query_controls(rosco_PS_Mode_0_tsr_interp, wind_speeds, 0.0) tsr_ps3 = query_controls(rosco_PS_Mode_3_tsr_interp, wind_speeds, 0.0) # Create figure fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) fig.suptitle(fr"Setpoint Trajectories") # Plot pitch - # ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) + ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") @@ -123,7 +130,7 @@ def main(): ax[0].grid(True) # Plot TSR - # ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) + ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") @@ -147,13 +154,13 @@ def main(): tsr_interp = abbas_tsr_interp, ) - # floris_PS_Mode_0_turbine = MITRotorTurbine( - # bem_model = bem, - # pitch_interp = rosco_PS_Mode_0_pitch_interp, - # pitch_rad = True, - # tsr_interp = rosco_PS_Mode_0_tsr_interp, - # rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, - # ) + floris_PS_Mode_0_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = rosco_PS_Mode_0_pitch_interp, + pitch_rad = True, + tsr_interp = rosco_PS_Mode_0_tsr_interp, + rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, + ) floris_PS_Mode_3_turbine = MITRotorTurbine( bem_model = bem, @@ -178,12 +185,12 @@ def main(): Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) - # fmodel_PS_Mode_0 = FlorisModel("defaults") - # fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - # fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) - # fmodel_PS_Mode_0.run() - # Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() - # Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) + fmodel_PS_Mode_0 = FlorisModel("defaults") + fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) + fmodel_PS_Mode_0.run() + Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() + Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) fmodel_PS_Mode_3 = FlorisModel("defaults") fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) @@ -203,10 +210,10 @@ def main(): wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", lw=3, linestyle = "solid", zorder = 1, ) - # ax1.plot( - # wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", - # lw=3, linestyle = "dashed", zorder = 1, - # ) + ax1.plot( + wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, + ) ax1.plot(wind_speeds, Ct_PS_Mode_3, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -224,10 +231,10 @@ def main(): wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "solid", zorder = 1, ) - # ax2.plot( - # wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - # lw=3, linestyle = "dashed", zorder = 1, - # ) + ax2.plot( + wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, + ) ax2.plot(wind_speeds, Cp_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) @@ -245,10 +252,10 @@ def main(): wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "solid", zorder = 1, ) - # ax3.plot( - # wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", - # lw=3, linestyle = "dashed", zorder = 1, - # ) + ax3.plot( + wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + lw=3, linestyle = "dashed", zorder = 1, + ) ax3.plot(wind_speeds, P_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", lw=3, linestyle = "dotted", zorder = 1, ) From 3b43c89bd9763dab041324c58e0f27a212908410 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 10:32:01 -0400 Subject: [PATCH 30/50] Update to Floris v5 --- examples/example_06_floris_integration.py | 2 +- poetry.lock | 364 +++++++++++++--------- pyproject.toml | 2 +- 3 files changed, 212 insertions(+), 156 deletions(-) diff --git a/examples/example_06_floris_integration.py b/examples/example_06_floris_integration.py index 78d6e7b..07f8c32 100644 --- a/examples/example_06_floris_integration.py +++ b/examples/example_06_floris_integration.py @@ -185,7 +185,7 @@ floris_annulus_umm_end = time.time() floris_Ct_annulus_umm = fmodel_annulus_umm.get_turbine_thrust_coefficients() floris_power_annulus_umm = np.squeeze(fmodel_annulus_umm.get_turbine_powers()) -floris_Cp_annulus_umm = floris_power_annulus_umm / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +floris_Cp_annulus_umm = floris_power_annulus_umm / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) # TODO: account for eff_ratio print("FLORIS UMM-BEM Annulus-Averaged: " + str(floris_annulus_umm_end - floris_annulus_umm_start) + " seconds") # solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged diff --git a/poetry.lock b/poetry.lock index 13fd70c..f12c5b7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "anyio" -version = "4.14.1" +version = "4.14.2" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72"}, - {file = "anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e"}, + {file = "anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494"}, + {file = "anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f"}, ] [package.dependencies] @@ -112,14 +112,14 @@ test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock [[package]] name = "asttokens" -version = "3.0.1" +version = "3.0.2" description = "Annotate AST trees with source code positions" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a"}, - {file = "asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7"}, + {file = "asttokens-3.0.2-py3-none-any.whl", hash = "sha256:9da13157f5b28becde0bd374fc677dcd3c290614264eff096f167c469cd9f933"}, + {file = "asttokens-3.0.2.tar.gz", hash = "sha256:3ecdbd8f2cc195f53ccada3a613538bb5f9ef6f6869129f13e03c30a677b8fe2"}, ] [package.extras] @@ -383,14 +383,14 @@ files = [ [[package]] name = "certifi" -version = "2026.6.17" +version = "2026.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main", "dev"] files = [ - {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"}, - {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"}, + {file = "certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775"}, + {file = "certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55"}, ] [[package]] @@ -1087,14 +1087,14 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "fastjsonschema" -version = "2.21.2" +version = "2.22.1" description = "Fastest Python implementation of JSON schema" optional = false -python-versions = "*" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"}, - {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"}, + {file = "fastjsonschema-2.22.1-py3-none-any.whl", hash = "sha256:cf377ff5c9a6f4f3125fb35f75a2c5767bd824ffbcf62c209a93cd48d1453999"}, + {file = "fastjsonschema-2.22.1.tar.gz", hash = "sha256:0b83d1ce8d7845b959dcb20e1a5c3c8883b6541d9c52ab02cce5166b75ec805f"}, ] [package.extras] @@ -1128,9 +1128,9 @@ docs = ["bokeh (>=3.7,<4.0)", "jupyter-book (>=1.0,<2.0)", "ruamel.yaml (>=0.18. [package.source] type = "git" -url = "https://github.com/misi9170/floris.git" -reference = "feature/user-def-op-mod" -resolved_reference = "27d5385eeb4e1a1bc88a95b41fcd52109bc78e0d" +url = "https://github.com/NatLabRockies/floris.git" +reference = "dev/v5-beta" +resolved_reference = "1093f89913034481d90a1f691d3393df284f6584" [[package]] name = "fonttools" @@ -1599,14 +1599,14 @@ notebook = "*" [[package]] name = "jupyter-builder" -version = "1.0.2" +version = "1.2.0" description = "JupyterLab build tools" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jupyter_builder-1.0.2-py3-none-any.whl", hash = "sha256:b024f65d36e1d530542db597b00dd513261aa59842e0d0fbbb1015a9f1935e9c"}, - {file = "jupyter_builder-1.0.2.tar.gz", hash = "sha256:6155d78a5325010532a6419ffcba89eac643fd1aa56ea83115e661924d6f6aab"}, + {file = "jupyter_builder-1.2.0-py3-none-any.whl", hash = "sha256:c8a003714a118ebb590f79b459e1e384dee7dce9aebaa86ace045f5960997fe4"}, + {file = "jupyter_builder-1.2.0.tar.gz", hash = "sha256:e62ed4a7e224c73197dd76974754c93070c9f0451ca450a2c81126838b00f866"}, ] [package.dependencies] @@ -1615,8 +1615,8 @@ tomli = {version = "*", markers = "python_version < \"3.11\""} traitlets = "*" [package.extras] -dev = ["build", "hatch", "mypy", "pre-commit", "ruff (==0.15.11)"] -test = ["copier (>=9.3,<10)", "coverage", "jinja2-time", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-cov"] +dev = ["build", "hatch", "mypy", "pre-commit", "ruff (==0.15.20)"] +test = ["copier (>=9.3,<10)", "coverage[toml] (>=7.10.6)", "deptry", "jinja2-time", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-cov (>=7)"] [[package]] name = "jupyter-client" @@ -1789,14 +1789,14 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.6.1" +version = "4.6.2" description = "JupyterLab computational environment" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jupyterlab-4.6.1-py3-none-any.whl", hash = "sha256:85a58546c831f3dce6cf919468c26874c9065e99c42279fb4abb8e1b552a98bb"}, - {file = "jupyterlab-4.6.1.tar.gz", hash = "sha256:75315982ed28427edaa62bb85eadb5105e4043a757643c910efd787fe6ed0837"}, + {file = "jupyterlab-4.6.2-py3-none-any.whl", hash = "sha256:5964447036629adfcd3fc0969effc1da6f47d2cbd0a60b2c2eea7c31be0ec6a8"}, + {file = "jupyterlab-4.6.2.tar.gz", hash = "sha256:e18ce8b34f3de350e93cd5b2c4f3ae884cbe266eb76bf5d6825a4ed34c13bcff"}, ] [package.dependencies] @@ -1814,6 +1814,7 @@ packaging = ">=23.2" tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} tornado = ">=6.2.0" traitlets = "*" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.12\""} [package.extras] dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.15.15)", "shellcheck-py"] @@ -2315,65 +2316,65 @@ dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setup [[package]] name = "matplotlib" -version = "3.11.0" +version = "3.11.1" description = "Python plotting package" optional = false python-versions = ">=3.11" groups = ["main", "examples"] markers = "python_version >= \"3.11\"" files = [ - {file = "matplotlib-3.11.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f857524b442f0f36e641868ce2171aafa88cb0bc0644f4e1d8a5df9b32649fef"}, - {file = "matplotlib-3.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:57baa92fdc82948ed716eae6d2579d4d6f40965cd8d2f416755b4a72580a3233"}, - {file = "matplotlib-3.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:630eee0e67d35cce2019a0e670719f4816e3b86aff0fa72729f6c69786fceb45"}, - {file = "matplotlib-3.11.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5106c444d0bf966eee2853548c03772af4ab7199118e086c62fbac8ccb07c055"}, - {file = "matplotlib-3.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d7aea652b58e686444079be3376ef546bffa1eee9b9bb9c472b9fcf6cf410d3"}, - {file = "matplotlib-3.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:70a5b3e9a5dab708c0f039709ae7c68d5b4d254e291ef76492cdba230c8bb5e4"}, - {file = "matplotlib-3.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:3d68266213e73823ac3be90615bab0cf31f88851e114cdb1dd25dacf3b01e1a7"}, - {file = "matplotlib-3.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:06b5872e9cf11adc8f589ded3ce11bc3e1061ad498259664fabc1f6615beb918"}, - {file = "matplotlib-3.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0515d495124be3124340e59f164d901ed4484e2246a5b74cfa483cac3b80bd97"}, - {file = "matplotlib-3.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be5f93a1d21981bfb802ded0d77a0caa92d4342a47d45754fac77e314a506344"}, - {file = "matplotlib-3.11.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41635d7909d19e52e924a521dde6d8f670b0f53ab1d0e8c331fa831554f681d1"}, - {file = "matplotlib-3.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:94f5000f67ca9faa300863ea17f8bce9175cb67b88bec4bc7780502d53dd7c9e"}, - {file = "matplotlib-3.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac6f1ef39f3d0f9e2463303013094992cdbe0f85f43bc54155bc472b2042768e"}, - {file = "matplotlib-3.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:9dd11fb612ce7bc60b1de5b4fc87ff959d22317b5de42aabf392f66f97af22eb"}, - {file = "matplotlib-3.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce3b839b34ae1f430b4616893a2945a2999debaa7e94e7e29a2a8bbf286f7b5"}, - {file = "matplotlib-3.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:373db8f91214e8ccaf35ac833cc1dd59dd961e148bbd55dd027141591dde1313"}, - {file = "matplotlib-3.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be152b7570324dc8d01574cc9474dd2d803237acf528bcbb5b211fa347461a09"}, - {file = "matplotlib-3.11.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:126f256df600652d7e4b394cf3164ff75210a00038f287c95a012a6f58d0e83f"}, - {file = "matplotlib-3.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:03acfeddf87b0dddb11b081ef7740ad445a3ca8bcb6b8e3011b08f2cf802b75c"}, - {file = "matplotlib-3.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:ab3722f04f3ff34c23b5012c5873d2894174e06c3822fcdac3610965a5ac7d06"}, - {file = "matplotlib-3.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:c945824670fb8915b4ac879e5e61f3c58e0913022f70a0de4c082b17372f8771"}, - {file = "matplotlib-3.11.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3489c3dc487669b4a980bc3068f87856de7a1564248d3f6c629efb2a58b03f24"}, - {file = "matplotlib-3.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6a98f5476ce784a50ce09998f4ae1e6a9f25043cef8a480c98949902eda74620"}, - {file = "matplotlib-3.11.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:565af866fd63e4bd3f987d580afe27c44c2552a3b3305f4ecbb85133601ea6f3"}, - {file = "matplotlib-3.11.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6b3e64dea5062c570f04358e2711859f3531b459f29516274fbad889079e4f3"}, - {file = "matplotlib-3.11.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:942b37c5db1899610bd1543ce8e13e4ecff9a4633e7f63bb6aa9205d2644ebd1"}, - {file = "matplotlib-3.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c08e649a6313e1291e713623b97a38e5bb4aa580b2a100a94a3309bc6b9c8eb3"}, - {file = "matplotlib-3.11.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2746cd2c113742ff6ce37a864c5ac5fd7aa644568f445e66166e457ac78e40e0"}, - {file = "matplotlib-3.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3338e3e3de128cf50d0d2fb92a122815daf9c755bd882a474343c05f8fd7ec79"}, - {file = "matplotlib-3.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:25c2e5455efd8d99f41fb79871a31feb7d301569642e332ec58d72cfe9282bc3"}, - {file = "matplotlib-3.11.0-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9695457a467ff86d23f35037a43deb6f1134dd6d3e2ac8ce1e2087cff09ffb9"}, - {file = "matplotlib-3.11.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19c16c61dea63b3582918503e6b294193961261d9daa806d4ae2151f1ad05430"}, - {file = "matplotlib-3.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2d72ea8b7924f3cb955e61518d21e43b3df1e6c8a793b480a0c1214f185d30ba"}, - {file = "matplotlib-3.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:1c02da0a629dfa9debf52725ea06866b74c1fb70a895bae05e4493d34074f9f2"}, - {file = "matplotlib-3.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aa55d73b3117d4b07f959cd9eb6f69b375d8df3414139c479388e551aa5d999d"}, - {file = "matplotlib-3.11.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a9d8c6e7cd2f0ddf11d8d92e520dd1d9d2abb0cf6ac8831e338666c81e905847"}, - {file = "matplotlib-3.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:be050fcf32f729eda99f7f75a80bf67612ce16ab9ac1c23a387dcaede95cb70e"}, - {file = "matplotlib-3.11.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfabef0230d0697aa0d717385194dd41162e00207a68bf4abf94c2bf4c27dca0"}, - {file = "matplotlib-3.11.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1644db30e759199443493ac5e5caec24fdb775a8f6123021f85ba47c4133c3cb"}, - {file = "matplotlib-3.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15b0d160079cb10699a0e98b5989c70677b2df7cacdc62af67c30f2facec46d9"}, - {file = "matplotlib-3.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:446307e6b04b57b1f1239e228a1ec2af0d589a1008cebc3dfa3f5441d095cfb6"}, - {file = "matplotlib-3.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:652fb5696271d4c50f196d22a5ff4f8e4444c74f847423570d7dc0aa2bbd0159"}, - {file = "matplotlib-3.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:81ae77077a1e16d37a5b61096ccb07c8d90a99b518fa8256b8f21578932f2f62"}, - {file = "matplotlib-3.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ddef37840695f5eef65f9f070fe2d2f510f584c2156203f9f622a5b0584efffd"}, - {file = "matplotlib-3.11.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cf662e5ac5707658cb931e19972c4bd99f7b4f8b7bf79d3c821d239fa6b71e64"}, - {file = "matplotlib-3.11.0.tar.gz", hash = "sha256:68c0c7be01b30dcca3638934f7f591df73401235cbdbf0d1ab1c71e7db7f8b57"}, + {file = "matplotlib-3.11.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b7cf158e7add54a8d51ac9b5a84abd6d4e13ed4951b4f25f1c5139f41c2addb2"}, + {file = "matplotlib-3.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2ace7273b9a5061a3b420918a16fae1f2dc5dfee1abcc13aba71b5d94b1820c"}, + {file = "matplotlib-3.11.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee55e9041211bf84302ab55ec3965df18dd90ae19f8b58332a7feaf208bfe83"}, + {file = "matplotlib-3.11.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f4bdeea33a8d15a071dbfe6d119451b1d719c733ac666d65357082901a9099"}, + {file = "matplotlib-3.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b4c78ceb2f11bcac7389d305cda17aeb1f4586a857854ab5780bd3dd8dbfc407"}, + {file = "matplotlib-3.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:7f33a781e12b1e53b278deb2f5373c2e55ec4f10727be3440c0cfb5cda9f944f"}, + {file = "matplotlib-3.11.1-cp311-cp311-win_arm64.whl", hash = "sha256:67e4c3cd578c65ebd81bdc09a1b6592ceafee6dfafe116dc85dfcb647b5bbb18"}, + {file = "matplotlib-3.11.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e15ef41507f3d525f46154ac9e3ae785dacde9f20e593a25de8986267892ef74"}, + {file = "matplotlib-3.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:21a67b961a6d597bca54fae826cd20695ba4a6e4d05424a08da6e13e3176fd6b"}, + {file = "matplotlib-3.11.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba8f811b8ddfac493734d6af0b2dff96919d0c28ca0d641858dab4262777c6ea"}, + {file = "matplotlib-3.11.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c52f7ad20ef476806ed212380b1d54d20310c8b86bdc2c9a68b51f0024a44472"}, + {file = "matplotlib-3.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b14eb22961fe865efb0e4ff167e333e428908b00115a8d800ccb65ee108e481"}, + {file = "matplotlib-3.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:88a2a27dd9691ae448dfae4b26f59036be90c3c28757edd3553a29559d00859f"}, + {file = "matplotlib-3.11.1-cp312-cp312-win_arm64.whl", hash = "sha256:480194afceca4df2f137c2721227d3cba67121fbf4397b69cee7f83714b0a58a"}, + {file = "matplotlib-3.11.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6771b0cd7838c6a857a7209814158c0ad09bfef878db3033dd82d70ad101f191"}, + {file = "matplotlib-3.11.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2abdee5ffa2fe11b2d19f7a5c63b785fb7c28cc46c7bc1814156341d9d1a33e1"}, + {file = "matplotlib-3.11.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0a19dcf73406d3746d25a5ed42d713604c9a3e024d129b102852b0d941cb9f3"}, + {file = "matplotlib-3.11.1-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7389b77ed2ab0552f46d9a90b81b7b8e6dfcdc42adc36c37a0865799843e0e3e"}, + {file = "matplotlib-3.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c90be0b73568da4f662afac580956a76e308437e641b4a45aa08925eeb67d95f"}, + {file = "matplotlib-3.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:68408341f2312836fbbdf6b3c78047f65b2d8752f5fd221c3e72d348f5b34f8b"}, + {file = "matplotlib-3.11.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c1f44890d435c1b4ef52f701ad5828cb450ea97bcc83918fda6be74965d6cd2"}, + {file = "matplotlib-3.11.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:5e510088c27a89d53580a752f959146893563e63c330e161d159b0fee652af6f"}, + {file = "matplotlib-3.11.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:1524e2bdd48a93557aa47ddcfe9c225dfdd57d5a01a5c49128c20f0632980ee1"}, + {file = "matplotlib-3.11.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:11664c551345553db92e61cae6cf1376f138f8c47cafdf13b64b18f3e3e9e464"}, + {file = "matplotlib-3.11.1-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e1f8922ba31959cf6a9dfb51be64b7f7bc582801a3957dc0c2f3afcd3537adf"}, + {file = "matplotlib-3.11.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83235693abde86e5e0129998f80ee39fc7f58e6d56a88fafb28a9278833e9d5f"}, + {file = "matplotlib-3.11.1-cp313-cp313t-win_amd64.whl", hash = "sha256:9a076f4fc5cdc43fdf510f5981418d25c2db4973418d9f22d8bb3dc8045ada78"}, + {file = "matplotlib-3.11.1-cp313-cp313t-win_arm64.whl", hash = "sha256:216fbb93a74add02ddb4cb38ef5348f59ac00b3e84567eaf16598772d40e150a"}, + {file = "matplotlib-3.11.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:30c492d4ba9448595b6fd8708c6725963f8148e25c0d8842948da5b05f0ee8d3"}, + {file = "matplotlib-3.11.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ac104be2768ffdd8655db9e71b768cbb45f2b9aa7b450cf1595e8f65d3822319"}, + {file = "matplotlib-3.11.1-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be943cb68bc6660ead58c55b3aa6366cba2ef7feb06460fbcce32360376f19f"}, + {file = "matplotlib-3.11.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5af0dcda57d471440a7b5b623e70e0a61003518443d9098f211a96ecfbbc25be"}, + {file = "matplotlib-3.11.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3d3fd84082b1afbd9398466c81309e20045be20d48fe0fb18c43504d164cbbb2"}, + {file = "matplotlib-3.11.1-cp314-cp314-win_amd64.whl", hash = "sha256:9601a1e90be21e4884c53b4f3dc3ee0544654946f9975258d691f1c2e2f119c6"}, + {file = "matplotlib-3.11.1-cp314-cp314-win_arm64.whl", hash = "sha256:ae30c6109848ac0f9fa36c5d6270938487614c47ba31860bd5361266dabc5685"}, + {file = "matplotlib-3.11.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:dadfe80797174e2984aae3be0b77594a3c72d2c0a40fbd4a0de48d2728caf3ae"}, + {file = "matplotlib-3.11.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:89b193b255f4f6f7948dbcee3691f4f341ab05d9a8874a67b45ddb4182922eda"}, + {file = "matplotlib-3.11.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:191163532cdefcb1571ca38a6d7e6474baccde64495783e6ba47aa07ec4b9bbb"}, + {file = "matplotlib-3.11.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9fdf1c818ab05d0e74002091ddaf414478a3a449ec9d51c8976d45be7e3a01e2"}, + {file = "matplotlib-3.11.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b937b9dba5f5f6c1e31c47abe2186c865c0914fd18f2ce0dfc39c9adcef5951d"}, + {file = "matplotlib-3.11.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f2912f647f3fbe1ccf085f91e213936f9101bead81a5e670565b1f1b3712f4fb"}, + {file = "matplotlib-3.11.1-cp314-cp314t-win_arm64.whl", hash = "sha256:54d47b8ae8b579633a3902ca5b4ad6c1e132a5626d64447b2e22a66394e79987"}, + {file = "matplotlib-3.11.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:427258425f9a3fc4ed79a91f9e9b9aaf5a82cb6571e85dc14063cc6fbb993741"}, + {file = "matplotlib-3.11.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:1ac697e591c11b6ad04679a73c2d2f9980fe9d9f0311fb414a2e329706343dfb"}, + {file = "matplotlib-3.11.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e4b9ac2f1f607ecda2af90a5232beee2af7582fce1cc30c4b6a1b012dc21ee99"}, + {file = "matplotlib-3.11.1.tar.gz", hash = "sha256:69647db5746941c793d6e445a4cd349323ffb87d9cc958c2ad84a659b4832d30"}, ] [package.dependencies] contourpy = ">=1.0.1" cycler = ">=0.10" -fonttools = ">=4.22.0" +fonttools = ">=4.28.2" kiwisolver = ">=1.3.1" numpy = ">=1.25" packaging = ">=20.0" @@ -2401,14 +2402,14 @@ test = ["flake8", "matplotlib", "nbdime", "nbval", "notebook", "pytest"] [[package]] name = "mistune" -version = "3.3.3" +version = "3.3.4" description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "mistune-3.3.3-py3-none-any.whl", hash = "sha256:99de1585e42dcbd826faa9e11a202727a5e202e4e4722a4c69ac1ff615793dd7"}, - {file = "mistune-3.3.3.tar.gz", hash = "sha256:c4c6c0c840b8637a2e9b8b6d607eb7c8f00888bf14c754409bcd339e848c2477"}, + {file = "mistune-3.3.4-py3-none-any.whl", hash = "sha256:ee015381e955e370962968befe1d729ab60fafb6a715ac6751763fbce38c8d4a"}, + {file = "mistune-3.3.4.tar.gz", hash = "sha256:58b5c96d6fcb61190dfe5fae498d2b2065f99cf61e9649418fd54cf1ada86dfe"}, ] [package.dependencies] @@ -2788,20 +2789,20 @@ test-extras = ["pytest-mpl", "pytest-randomly"] [[package]] name = "notebook" -version = "7.6.0" +version = "7.6.1" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "notebook-7.6.0-py3-none-any.whl", hash = "sha256:98aa2811b54ac191321d5dfce12ca700f8a511a33a26e4de2fa106a357c43d6a"}, - {file = "notebook-7.6.0.tar.gz", hash = "sha256:ea13e79e601bf273074895fdfb17dd3f2da916d3c045e0b9c47d18b16ab62481"}, + {file = "notebook-7.6.1-py3-none-any.whl", hash = "sha256:6ea1e4c926f0dc490444ddcc335797a3dacda470a805d01031872fb119988ba2"}, + {file = "notebook-7.6.1.tar.gz", hash = "sha256:0b45fd1010668dd4808c40914d957706dbf044a677d28764dc881b74dfcede82"}, ] [package.dependencies] jupyter-builder = ">=1.0.2,<2" jupyter-server = ">=2.19.0,<3" -jupyterlab = ">=4.6.0,<4.7" +jupyterlab = ">=4.6.2,<4.7" jupyterlab-server = ">=2.28.0,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" @@ -2836,6 +2837,7 @@ description = "Fast numerical expression evaluator for NumPy" optional = false python-versions = ">=3.10" groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "numexpr-2.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0fab3fd06a04f6b86102552b26aa5d85e20ac7d8296c15764c726eeabae6cc8"}, {file = "numexpr-2.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:64ae5dfd62d74a3ef82fe0b37f80527247f3626171ad82025900f46ffca4b39a"}, @@ -2899,6 +2901,66 @@ files = [ [package.dependencies] numpy = ">=1.23.0" +[[package]] +name = "numexpr" +version = "2.14.2" +description = "Fast numerical expression evaluator for NumPy" +optional = false +python-versions = ">=3.11" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "numexpr-2.14.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2aa65ddc2243f19c6915f34ee0978b4a2df20f297230a793c4ee6d55f3472599"}, + {file = "numexpr-2.14.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf959e6df6cb603611c034b6cba7b03a361be0ad0b80b73f163fab95f5ccbb7f"}, + {file = "numexpr-2.14.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d534ecb456a4ae3995f99c8a5deb469bfff05d4ec610a7885c175c881d12f710"}, + {file = "numexpr-2.14.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f41170e9d0dbba76851e35d80cfa9f4ca5fe78628c5bf24d941cf3364940ab7a"}, + {file = "numexpr-2.14.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6acafb2fdbeaaa6681a8f1a1d8b3f7dcd33704baace7057b950754b258be7c43"}, + {file = "numexpr-2.14.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7ca9e71195b36cc7aeafe97347549e1e1c1e889ff700238782ef6447651ec26d"}, + {file = "numexpr-2.14.2-cp311-cp311-win32.whl", hash = "sha256:779129d50974e7d6d6581d322f75b8f8375e96215b6861a2d5460347997ef649"}, + {file = "numexpr-2.14.2-cp311-cp311-win_amd64.whl", hash = "sha256:2f132777d7d425471c458af5617e023402f13f5006301eacf8a1a6e7118ea70c"}, + {file = "numexpr-2.14.2-cp311-cp311-win_arm64.whl", hash = "sha256:f1de5c88515ed9fbcad42699a0e2b5821b4d0f0adb0da6fb7e009e5cb19d8493"}, + {file = "numexpr-2.14.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:606ceaf5722e295ef965ca591736fc26d9e5f13ad950a479e64cead1947f8a3d"}, + {file = "numexpr-2.14.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:790da022539fe7c37dc893acf530a91c2ca6964d7ba11f464131383729d058f3"}, + {file = "numexpr-2.14.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:327be9ee62251c173236dc620147ff2d0e732a32f5bad918d78a10082f502f63"}, + {file = "numexpr-2.14.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6a5d8fc7016bf6f6e1808b011510aa7c3bd75ec1407f7650874ec591db59f5e"}, + {file = "numexpr-2.14.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4b1ff261c3e69c4c59578d3a9ca6132603619d38ae1abe73325563bed3b9bbaf"}, + {file = "numexpr-2.14.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b8384592c49cb15a91caa54e2cd84d1ce18edb7af030bb76cd29b52e5dc155d"}, + {file = "numexpr-2.14.2-cp312-cp312-win32.whl", hash = "sha256:41cdeacf1b4e51c1143983ea61fcee68139ca47222b55a9265b4fa73826c4260"}, + {file = "numexpr-2.14.2-cp312-cp312-win_amd64.whl", hash = "sha256:8fc55d14bcf17b3fe69213bea14f999451892b4690717008c66f2edfd6a085ce"}, + {file = "numexpr-2.14.2-cp312-cp312-win_arm64.whl", hash = "sha256:806a4471310fe20aa7cb1b2816a6f5e508073a1ad1c2e18041b83e57066fad6a"}, + {file = "numexpr-2.14.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0741efbd75c284e709b0fd430c85c31982b44c9962922ba8a9cbbea1bf413321"}, + {file = "numexpr-2.14.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92b00c78664070e3af155c6be713a0a5d75d598647ce32a5609adb79a8f961d3"}, + {file = "numexpr-2.14.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:149ab5744a5222f07b1d60455c4021c754d395e44938944ac7c7c2495f7feb54"}, + {file = "numexpr-2.14.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd2f5882a66a7792aa6614c68831aa20085b499d41422aedd001080624ebb14c"}, + {file = "numexpr-2.14.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:375d8bee15be42dab22100a0a3de05fe6689a2de853eca012858768a9a7e02ab"}, + {file = "numexpr-2.14.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c1ffaf805d8636c3f95d0996517ecf9684c9ac62d768030ca78d1d00af2b3504"}, + {file = "numexpr-2.14.2-cp313-cp313-win32.whl", hash = "sha256:449a57fb9d38de136e742b1fc429572b42f29778f1d695c3fe50ffec9d3c9a71"}, + {file = "numexpr-2.14.2-cp313-cp313-win_amd64.whl", hash = "sha256:dd905922d7dce457947d54b84c7ac345cef37332b724445e159a5a1a2080ce2b"}, + {file = "numexpr-2.14.2-cp313-cp313-win_arm64.whl", hash = "sha256:b02738853b9b5b8a995f6c680f8f6ef33e8f419395b8fa380e38690495fdb911"}, + {file = "numexpr-2.14.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:76e87c7bd70d721ce4d418e81f4fb7ecf9e7e67d7cea8102527b07fd3d3facf9"}, + {file = "numexpr-2.14.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:939c89f613b814e64bb568859397dc9f99b219c3ef681a72fb99a86e435262f9"}, + {file = "numexpr-2.14.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b20c1c55aba7812ff2f2c6a50006425d02282fabb1eaf8d75fe638ffcf6deb02"}, + {file = "numexpr-2.14.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bac00898930f962f360c3d763a8e2273fc931f65a1759ff1bf64b3cf13d65aee"}, + {file = "numexpr-2.14.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:022e61a3d5dbf5807746264b62126d1c2c24057ad90052478a4d4482ab2555c2"}, + {file = "numexpr-2.14.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1d4593e2c6fa060cd7441e8b6ef25c16321a6be2144b3c82d1e00885f1fb6e94"}, + {file = "numexpr-2.14.2-cp314-cp314-win32.whl", hash = "sha256:66f3b125b1104241322811de87918724d6709bf082dc0703722d0cecb7b29e82"}, + {file = "numexpr-2.14.2-cp314-cp314-win_amd64.whl", hash = "sha256:ef576a1cded27ba2f3129bc3c42df452a1c498072680d560793f98b0024cd7e6"}, + {file = "numexpr-2.14.2-cp314-cp314-win_arm64.whl", hash = "sha256:8274c51ae1842948f3ae7fe6951a23dcf4ddcbeeaff3737e978e7740b754662d"}, + {file = "numexpr-2.14.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f3526699350f94c6277fb16863773a1af9defd95a6f78bbd69b1f0338fd94756"}, + {file = "numexpr-2.14.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:91e7928435f14fcb351c0157000bce65122b897cc8b0df6bcc48251f25850a6d"}, + {file = "numexpr-2.14.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c66925deb968f0b5280f723e2bb5918c11e6be2ca60e9e1530006286ab44031d"}, + {file = "numexpr-2.14.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a404c9a55902572eec810068d06b79a7c99e96f0400f5a7d73f39dff5ec5e371"}, + {file = "numexpr-2.14.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:44dc6b1dfa9abcbfc9917297f0d2af7c87c16b6ecd45747a8e70f54399a3a2f9"}, + {file = "numexpr-2.14.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:93233040f4bed3bce5abb0c2d20aeb1074511f29cbaa9c14828f86bcfa44d321"}, + {file = "numexpr-2.14.2-cp314-cp314t-win32.whl", hash = "sha256:2aceefa08f8f86317fa6e8fe9f6dc20d24ab8365d715be4a26306acf406d2dbe"}, + {file = "numexpr-2.14.2-cp314-cp314t-win_amd64.whl", hash = "sha256:cd684ac9daa539fcdac3437678834797b29d7780cfaad71111745132d466d51f"}, + {file = "numexpr-2.14.2-cp314-cp314t-win_arm64.whl", hash = "sha256:2ef72de3d3dd466cb0c435cae7141c99b0f8091b1eae9d03dcb38690f56c3f79"}, + {file = "numexpr-2.14.2.tar.gz", hash = "sha256:e7144e83ea9e581f2273e0304f15836736c4e470e2bd2e378ce617662a1ca278"}, +] + +[package.dependencies] +numpy = ">=1.26.0" + [[package]] name = "numpy" version = "2.2.6" @@ -3128,14 +3190,14 @@ xlrd = ["xlrd (>2.0)"] [[package]] name = "openmdao" -version = "3.44.0" +version = "3.45.0" description = "OpenMDAO framework infrastructure" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "openmdao-3.44.0-py3-none-any.whl", hash = "sha256:4494b7c04d09751c60053c1fc2098bf05c93298deb98011ae66f09167601113c"}, - {file = "openmdao-3.44.0.tar.gz", hash = "sha256:2aea7aafe3f4bda5052607654ecc719bcca48aaa2f7e88471bcf1a382b3a6c5d"}, + {file = "openmdao-3.45.0-py3-none-any.whl", hash = "sha256:ef01406fc29e763b69b979ffe7a3652351de5a68653da478cd4bbe02e2318f90"}, + {file = "openmdao-3.45.0.tar.gz", hash = "sha256:2e342398386230706999433a0eafc3df566e71f89709479323c3f00ab1b69e54"}, ] [package.dependencies] @@ -3341,61 +3403,55 @@ xml = ["lxml (>=4.9.2)"] [[package]] name = "pandas" -version = "3.0.3" +version = "3.0.5" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.11" groups = ["main"] markers = "python_version >= \"3.11\"" files = [ - {file = "pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:455f6f8139d4282188f526868dbc3c828470e88a3d9d59a891bd46a455f21b98"}, - {file = "pandas-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4e15135e2ee5df1063313e2425ceef8ac0f4ae775893815b0923651b806a5639"}, - {file = "pandas-3.0.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:05f1f1752b8533ea03f7f39a9c15b1a058d067bb48f4748948e7a8691e0510f2"}, - {file = "pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a1e45c80cceb3b4a21bc5939d52e8cbd8d9b7305309219d59e9754d9ce09e27"}, - {file = "pandas-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:14da8316da4d0c5a77618425996bfb1248ca87fc2c1486e6fde4652bd18b5824"}, - {file = "pandas-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a55066a0505dae0ba2b50a46637db34b46f9094c65c5d4800794ef6335010938"}, - {file = "pandas-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6674ab18ad8c57802867264b00e15e7bb904700cdd9046e3b2fa1fce237439ea"}, - {file = "pandas-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:5cc09a68b3120e0f54870dede8287a7bb1fa463907e4fcec1ea77cab6179bf7a"}, - {file = "pandas-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09"}, - {file = "pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4"}, - {file = "pandas-3.0.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c"}, - {file = "pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9"}, - {file = "pandas-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf"}, - {file = "pandas-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c"}, - {file = "pandas-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc"}, - {file = "pandas-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49"}, - {file = "pandas-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa"}, - {file = "pandas-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7"}, - {file = "pandas-3.0.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8"}, - {file = "pandas-3.0.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a"}, - {file = "pandas-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb"}, - {file = "pandas-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2"}, - {file = "pandas-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44"}, - {file = "pandas-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e"}, - {file = "pandas-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d"}, - {file = "pandas-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066"}, - {file = "pandas-3.0.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd"}, - {file = "pandas-3.0.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085"}, - {file = "pandas-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870"}, - {file = "pandas-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f"}, - {file = "pandas-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13"}, - {file = "pandas-3.0.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3650109c0f22879df8bd6179ab9ee3d7f1d1d4e7e0094a3f0032d9f51e2e64ac"}, - {file = "pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f"}, - {file = "pandas-3.0.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba7e08b9ac1d54569cd1e256e3668975ed624d6826f7b68df0342b012007bddb"}, - {file = "pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a"}, - {file = "pandas-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3a2ec42c98ffa2565a67e08e218d06d72576d758d90facb7c00805194d8f360"}, - {file = "pandas-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:335f62418ed562cfc3c49e9e196375c28b729dcef8543abf4f9438e381bf3c76"}, - {file = "pandas-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5"}, - {file = "pandas-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:a2d2dff8a04f3917b55ab3910c32990f8ddf7eceba114947838cefa976a68977"}, - {file = "pandas-3.0.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:0d589105b3c14645af1738ff279b2995102d8f7a03b0a66dc8d95550eb513e04"}, - {file = "pandas-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:13fc1e853d9e04743d11ba75a985ccbc2a317fe07d8af61e445a6fd24dacd6a6"}, - {file = "pandas-3.0.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:819959dab7bbd0049c15623fbac4e29a191b9528160a61fb1032242d8ced2d9c"}, - {file = "pandas-3.0.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:60ae316d3fd75d1858d450d0db0103ea2be3e7d4a95ec2f064f7e2ae63f7b028"}, - {file = "pandas-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd3a518890b400d32f9023722dc9a9a5c969f00b415419a3c06c043f09bb5d7d"}, - {file = "pandas-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9c39be2d709d01fa972a0cabc522389fceca4f3969332ba25a7d6c5802cf976a"}, - {file = "pandas-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4db8c527972a821cf5286b40ccc57642a39bc62e62022b42f99f8a67fca8c3a1"}, - {file = "pandas-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1"}, - {file = "pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc"}, + {file = "pandas-3.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2946e77e4a53cd248cbde631a12f0e51c8324ce354c3eba4d20147c1ad6f4282"}, + {file = "pandas-3.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71ecc8fb7ed1a7aa4392316b5309a6347e8e7f832f38fd897846b3a1457a9298"}, + {file = "pandas-3.0.5-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b173f5951ff6b8b0ec7675e20dff3c97b7e7a57dfcce387c2d7c5afe87cb7899"}, + {file = "pandas-3.0.5-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2c0cf1dd9b55a22d105fc46c1b489af3bd42264fcba7c66297bf47a9a1d9c78a"}, + {file = "pandas-3.0.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0fac0010c75e4efb6b99e249c183a8993ce0dc95c240f9b120a5e67c727b7928"}, + {file = "pandas-3.0.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:08d24fe11a17dc33bd6e937dc9c665f9cba08fbdc9f657f405713515febe300d"}, + {file = "pandas-3.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b1261758dfb6cf12c3cff8300e21cefad30e7ec709abb4c24ac7318e6a52462a"}, + {file = "pandas-3.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:679f4e85b30ddb1515458ab1e788d3e260eae369b1f78da7a3aa4cac8ebf4a2a"}, + {file = "pandas-3.0.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fa290c16964d4963fbfbc358928239cf3bd755b20e988ce944877def2f44471d"}, + {file = "pandas-3.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c2e26bb46934b8a2ca0c3de1d3d606fc5f6746584791b2db264d58cf370e08dc"}, + {file = "pandas-3.0.5-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:73fa87b08a7ef706f8aafda39ddaccf2a99047bea62d8c88a0361bcafb2237bc"}, + {file = "pandas-3.0.5-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d373ce03ffd84010ed9839fa73672a9c8256990532e158440c0085db7d914b34"}, + {file = "pandas-3.0.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2a29c53d85ea98c5e792c59ef82ee9fbe6ca902c0d0adb6b23f45ef894cd7bf6"}, + {file = "pandas-3.0.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a5ad3b02ed6bc7d7ae9b70804b2c6aa31827489d150f8e623ce82491b82085d7"}, + {file = "pandas-3.0.5-cp312-cp312-pyemscripten_2024_0_wasm32.whl", hash = "sha256:b2acb4650527eec6822c3dadb2b771277b65e7dae7a267d4bccf65fd1bb3fbce"}, + {file = "pandas-3.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:80a611068e8a3ac23f7398c6c14eb46dc974e5cc9997f653e2dcfd1da74edd41"}, + {file = "pandas-3.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:25ff585b972a18ef1fe9ffa3ac6544d9950508aa76832e5147640b6022821e49"}, + {file = "pandas-3.0.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c1c05a767fe8e5b4fe9e1c29806829c582052eaedb9120a3da83ba3f69e24a5b"}, + {file = "pandas-3.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b86765f268b56f7e665b93bce9d5df69dee7f99e595cf8fb839483ab315942a3"}, + {file = "pandas-3.0.5-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c597ecf5616b5c420372c1d4d4c00dbbfba7398bea857dcc984347e1ea48417b"}, + {file = "pandas-3.0.5-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4b11c36e218331d0387cbe3a0a5f75162357a1d92d57b2b08a336ff94b19b2be"}, + {file = "pandas-3.0.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf52e1f61d229496da17dc7ab54acdee627357e7008fd4fecba3d0ba2937fa58"}, + {file = "pandas-3.0.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:db172144bb56422bd157812f3b021eacc255451470b31e2c633c349490a1cfee"}, + {file = "pandas-3.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:0d298e951f23016ce4699951d044ae6418dbc91bf68cefca0f77666fcbb4e5c6"}, + {file = "pandas-3.0.5-cp313-cp313-win_arm64.whl", hash = "sha256:66266d3442a5e8b3c90274c2b8b230bee42dd1c286bc822cc2f9f2c7e12b883e"}, + {file = "pandas-3.0.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2f264fc46911cc8131a7322a16199bbf8e353d27c10bb211f5bd0c814324dc36"}, + {file = "pandas-3.0.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:53730687fcd161883b24e10411c06d6a4c0f2275d2faf3bb2bc25deb4ba8007c"}, + {file = "pandas-3.0.5-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:960d3ebcf249f75206899fcd2c6de53f736b7265759ced0d3e559df0b8b709b0"}, + {file = "pandas-3.0.5-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e94c2c5ca43bd3ca32bf64d32308887b65e5f9bfd8023ea52755107a999f93b"}, + {file = "pandas-3.0.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e819dd5f62966b481a8cb649d3299ebd886a1ea91ed5a99bf7ce77c98d18ab94"}, + {file = "pandas-3.0.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3c5ed2e7c06e91d340dfd091d7934f9bc82e4a36b95f647f090b9d1c9ac649da"}, + {file = "pandas-3.0.5-cp314-cp314-win_amd64.whl", hash = "sha256:cd8f7c6dc98527058ee6264219343f5392240a6f1bfa654fc5d79023020d0c92"}, + {file = "pandas-3.0.5-cp314-cp314-win_arm64.whl", hash = "sha256:5183427f5a8156d480f30333777bc978be93650a49a7c01db26adffe95b31e85"}, + {file = "pandas-3.0.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:303da736987d481074ca720ada325f8bd80c64ebc2d45ed79b29df3aaa4a26ca"}, + {file = "pandas-3.0.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3b2801bbb049d0136f6c213eae02b5fca969384fc2064dd728d8620552aa49da"}, + {file = "pandas-3.0.5-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cce3a9d11d2b1f82c69a27ec1f4948a170e2c403c4bbfa8cca62e3fdebe2ef3a"}, + {file = "pandas-3.0.5-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef01af4d8dc6cd2c8d6c7736f149574ef93fe043811eeb5e445f2647154b5040"}, + {file = "pandas-3.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e2759e890db96dfcffdbd9b86c3c2cb6afaf58def482820317e06163ec1066cd"}, + {file = "pandas-3.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b58b1b39d46a5862e3fb18f50d1a201398619d16a0f9f73f57eea5583cf0e63c"}, + {file = "pandas-3.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:1c10461f6eeb35d8f05b6184c65c8b9991663b66c46b1d559b682cb34ae7c6ea"}, + {file = "pandas-3.0.5-cp314-cp314t-win_arm64.whl", hash = "sha256:3c5015fd1730fbf883647e88068176c839c102cea883ba1769a6f4593bfc1f8c"}, + {file = "pandas-3.0.5.tar.gz", hash = "sha256:dca3734d6ab7c906e6730f0788b0a1dbb9f2467731f9711f77995c8e9d62d712"}, ] [package.dependencies] @@ -3428,7 +3484,7 @@ postgresql = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "psyc pyarrow = ["pyarrow (>=13.0.0)"] spss = ["pyreadstat (>=1.2.8)"] sql-other = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)"] -test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)"] +test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4,<9.1)", "pytest-xdist (>=3.6.1)"] timezone = ["pytz (>=2020.1)"] xml = ["lxml (>=5.3.0)"] @@ -3636,14 +3692,14 @@ xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.10.0" +version = "4.11.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a"}, - {file = "platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7"}, + {file = "platformdirs-4.11.0-py3-none-any.whl", hash = "sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74"}, + {file = "platformdirs-4.11.0.tar.gz", hash = "sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0"}, ] [[package]] @@ -3728,14 +3784,14 @@ dill = ["dill (>=0.4.1)"] [[package]] name = "prometheus-client" -version = "0.25.0" +version = "0.26.0" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1"}, - {file = "prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28"}, + {file = "prometheus_client-0.26.0-py3-none-any.whl", hash = "sha256:fa93d06737aa02bacd05794768508bb97d2fbee28cb3bca04eaae92f0ca953d6"}, + {file = "prometheus_client-0.26.0.tar.gz", hash = "sha256:04a91bcf94e2cf74a44a1a874d651a2e853ed354b6e822f3b7487751465d5c2b"}, ] [package.extras] @@ -3745,18 +3801,18 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.52" +version = "3.0.53" description = "Library for building powerful interactive command lines in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"}, - {file = "prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"}, + {file = "prompt_toolkit-3.0.53-py3-none-any.whl", hash = "sha256:01c0891d7f9237d5e339f7d3e42cdae80b7534abb1c7c0e3352efba6231492f2"}, + {file = "prompt_toolkit-3.0.53.tar.gz", hash = "sha256:9ec8a0ad96d5c56148b3f914aa79c1564c3fde5d2e6b876e7bc327e353cf8fa6"}, ] [package.dependencies] -wcwidth = "*" +wcwidth = ">=0.1.4" [[package]] name = "psutil" @@ -4000,15 +4056,15 @@ unidecode = ["Unidecode (>=1.1.1)"] [[package]] name = "pytz" -version = "2026.2" +version = "2026.3.post1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" groups = ["main"] markers = "python_version < \"3.11\"" files = [ - {file = "pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126"}, - {file = "pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a"}, + {file = "pytz-2026.3.post1-py2.py3-none-any.whl", hash = "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815"}, + {file = "pytz-2026.3.post1.tar.gz", hash = "sha256:2211d3fcf9a797d3405cac96ac7f61d80e6a644f72a3309607282fe8a2010c5d"}, ] [[package]] @@ -5030,14 +5086,14 @@ files = [ [[package]] name = "soupsieve" -version = "2.8.4" +version = "2.9.1" description = "A modern CSS selector implementation for Beautiful Soup." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "soupsieve-2.8.4-py3-none-any.whl", hash = "sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65"}, - {file = "soupsieve-2.8.4.tar.gz", hash = "sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e"}, + {file = "soupsieve-2.9.1-py3-none-any.whl", hash = "sha256:4f4477399246b7a0c720a88ca2454b11cd6bb9ae4c9d170140786e916776c14c"}, + {file = "soupsieve-2.9.1.tar.gz", hash = "sha256:c33e6605bbc71dd628b00c632d58ae607c22bade247e52553928f83bbb75b4ba"}, ] [[package]] @@ -5263,14 +5319,14 @@ files = [ [[package]] name = "tqdm" -version = "4.68.4" +version = "4.70.0" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.8" groups = ["main", "examples"] files = [ - {file = "tqdm-4.68.4-py3-none-any.whl", hash = "sha256:5168118b2368f48c561afda8020fd79195b1bdb0bdf8086b88442c267a315dc2"}, - {file = "tqdm-4.68.4.tar.gz", hash = "sha256:19829c9673638f2a0b8617da4cdcb927e831cd88bcfcb6e78d42a4d1af131520"}, + {file = "tqdm-4.70.0-py3-none-any.whl", hash = "sha256:7f585706bfddbdebf89daac705b2dfcc16890130727d3197ca62c732b4310953"}, + {file = "tqdm-4.70.0.tar.gz", hash = "sha256:55b0b0dbd97462d06ebee91e4dac24ed4d4702be82b24f07e6c1d27e08cea220"}, ] [package.dependencies] @@ -5626,4 +5682,4 @@ viz = ["cartopy (>=0.24)", "matplotlib (>=3.10)", "nc-time-axis", "seaborn"] [metadata] lock-version = "2.1" python-versions = ">3.10, <3.15" -content-hash = "aec736c656dc40fed742849be1fd4d9d6426518d6bc5ca1062dafdbb7b2cab23" +content-hash = "917ef746b4a52e48fabccd07a22188031c78cfa94486416eb2af678990491c26" diff --git a/pyproject.toml b/pyproject.toml index 5efce37..c270e91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ numpy = "^2.2.1" scipy = ">=1.6" unified-momentum-model = {git = "https://github.com/Howland-Lab/Unified-Momentum-Model.git"} pyyaml = "^6.0.1" -floris = {git = "https://github.com/misi9170/floris.git", branch = "feature/user-def-op-mod"} +floris = {git = "https://github.com/NatLabRockies/floris.git", branch = "dev/v5-beta"} rosco = "^2.10.4" ruamel-yaml = "^0.19.1" seaborn = "^0.13.2" From 1686caa0f8977396c2ed98f12cc3eff664509f87 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 10:39:41 -0400 Subject: [PATCH 31/50] Add x0 --- MITRotor/FlorisInterface/FlorisInterface.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index b720207..b16f988 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -90,6 +90,7 @@ class MITRotorTurbine(BaseOperationModel): _u4 = field(init=False, default=None, type = NDArrayFloat) _v4 = field(init=False, default=None, type = NDArrayFloat) _w4 = field(init=False, default=None, type = NDArrayFloat) + _x0 = field(init=False, default=None, type = NDArrayFloat) _power = field(init=False, default=None, type = NDArrayFloat) # calculate a few needed fields post-initialization @@ -129,6 +130,7 @@ def _update_solution(self, self._u4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._v4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._w4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) + self._x0 = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._power = np.empty((n_findex, n_turbines), dtype=floris_float_type) # compute the power-effective wind speed across the rotor @@ -165,6 +167,7 @@ def _update_solution(self, self._u4 = bem_sol.u4, self._v4 = bem_sol.v4 self._w4 = bem_sol.w4 + self._x0 = bem_sol.x0 # compute power self._power[:, tindex] = ( 0.5 * bem_sol.Cp() * air_density * rotor_area @@ -187,4 +190,4 @@ def axial_induction(self, **kwargs) -> NDArrayFloat: def near_wake_velocities(self, **kwargs) -> NDArrayFloat: self._update_solution(**kwargs) - return (self._u4, self._v4, self._w4) \ No newline at end of file + return (self._u4, self._v4, self._w4, self._x0) \ No newline at end of file From f1c01a8464bb8c21031ec506e58f439d5ba4fbdd Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 10:43:08 -0400 Subject: [PATCH 32/50] Extra debugging --- MITRotor/FlorisInterface/ROSCOInterface.py | 1 + MITRotor/FlorisInterface/ROSCOUtilities.py | 0 MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml | 2 +- analyze_crash_log.py | 120 +++++++ examples/example_08_floris_rosco.py | 13 +- examples/example_08_floris_rosco2.py | 307 ++++++++++++++++++ 6 files changed, 435 insertions(+), 8 deletions(-) delete mode 100644 MITRotor/FlorisInterface/ROSCOUtilities.py create mode 100644 analyze_crash_log.py create mode 100644 examples/example_08_floris_rosco2.py diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 93050d9..0910a36 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -348,6 +348,7 @@ def _run_one_wind_row( except Exception: # leave NaN and continue to next yaw + print("HELLO") if controller_int is not None: try: controller_int.kill_discon() diff --git a/MITRotor/FlorisInterface/ROSCOUtilities.py b/MITRotor/FlorisInterface/ROSCOUtilities.py deleted file mode 100644 index e69de29..0000000 diff --git a/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml index 15f0975..2a65efd 100644 --- a/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml +++ b/MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml @@ -31,7 +31,7 @@ controller_params: F_LPFType: 2 # {1: first-order low-pass filter, 2: second-order low-pass filter}, [rad/s] (currently filters generator speed and pitch control signals) F_NotchType: 0 # Notch on the measured generator speed {0: disable, 1: enable} IPC_ControlMode: 0 # Turn Individual Pitch Control (IPC) for fatigue load reductions (pitch contribution) {0: off, 1: 1P reductions, 2: 1P+2P reductions} - VS_ControlMode: 2 # Generator torque control mode in above rated conditions {0: constant torque, 1: constant power, 2: TSR tracking PI control} + VS_ControlMode: 1 # Generator torque control mode in above rated conditions {0: constant torque, 1: constant power, 2: TSR tracking PI control} PC_ControlMode: 1 # Blade pitch control mode {0: No pitch, fix to fine pitch, 1: active PI blade pitch control} Y_ControlMode: 0 # Yaw control mode {0: no yaw control, 1: yaw rate control, 2: yaw-by-IPC} SS_Mode: 1 # Setpoint Smoother mode {0: no setpoint smoothing, 1: introduce setpoint smoothing} diff --git a/analyze_crash_log.py b/analyze_crash_log.py new file mode 100644 index 0000000..bc2443c --- /dev/null +++ b/analyze_crash_log.py @@ -0,0 +1,120 @@ +import re +import matplotlib.pyplot as plt +import numpy as np +import matplotlib as mpl +from matplotlib.lines import Line2D + +def get_vals(logfile): + + # Parse lines that contain exactly 5 numbers: + # wind_speed, yaw, blade_pitch, tsr, avg_runtime + rows = [] + num_re = r"[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?" + + with open(logfile, "r", encoding="utf-8", errors="ignore") as f: + for line in f: + nums = re.findall(num_re, line) + if len(nums) == 5: + rows.append(tuple(map(float, nums))) + + if not rows: + raise RuntimeError("No 5-number data lines found in crash.log") + + wind, yaw, pitch, tsr, runtime = zip(*rows) + + wind = np.array(wind, dtype=float) + yaw = np.array(yaw, dtype=float) + pitch = np.array(pitch, dtype=float) + tsr = np.array(tsr, dtype=float) + runtime = np.array(runtime, dtype=float) + + # ---- filter unrealistic pitch values ---- + # Set these for your units: + # degrees example: -5 to 45 + # radians example: -0.1 to 0.8 + PITCH_MIN, PITCH_MAX = -5.0, 45.0 + + m = ( + np.isfinite(pitch) & np.isfinite(tsr) & np.isfinite(runtime) & + (pitch >= PITCH_MIN) & (pitch <= PITCH_MAX) & (wind >= 3) + ) + wind = wind[m] + pitch = pitch[m] + yaw = yaw[m] + tsr = tsr[m] + runtime = runtime[m] + return wind, pitch, yaw, tsr, runtime + +logfile1 = "crash_ps_3_yaw.log" +wind1, pitch1, yaw1, tsr1, runtime1 = get_vals(logfile1) + +logfile2 = "crash_ps_0_yaw.log" +wind2, pitch2, yaw2, tsr2, runtime2 = get_vals(logfile2) + +# 1) time vs wind speed, colored by yaw +plt.figure(figsize=(6, 4)) +sc = plt.scatter(wind1, runtime1, c=yaw1, cmap="viridis", alpha = 0.7, s=35) +plt.xlabel("Wind speed") +plt.ylabel("Average runtime") +plt.colorbar(sc, label="Yaw") +plt.tight_layout() +plt.savefig("time_vs_windspeed_colored_by_yaw.png", dpi=200) +plt.close() + +# 2) time vs tsr, colored by wind speed +plt.figure(figsize=(6, 4)) +sc = plt.scatter(tsr1, runtime1, c=yaw1, cmap="plasma", alpha = 0.7, s=35) +plt.xlabel("TSR") +plt.ylabel("Average runtime") +plt.colorbar(sc, label="Yaw") +plt.tight_layout() +plt.savefig("time_vs_tsr_colored_by_yaw.png", dpi=200) +plt.close() + +# 3) time vs wind speed, colored by tsr +plt.figure(figsize=(6, 4)) +sc = plt.scatter(wind1, runtime1, c=tsr1, cmap="plasma", alpha = 0.7, s=35) +plt.xlabel("Windspeed") +plt.ylabel("Average runtime") +plt.colorbar(sc, label="TSR") +plt.tight_layout() +plt.savefig("time_vs_wind_colored_by_tsr.png", dpi=200) +plt.close() + +# 4) time vs tsr colored by pitch + +# shared color normalization across both datasets +pitch1_deg = np.rad2deg(pitch1) +pitch2_deg = np.rad2deg(pitch2) +vmin = min(np.min(pitch1_deg), np.min(pitch2_deg)) +vmax = max(np.max(pitch1_deg), np.max(pitch2_deg)) +norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax) +cmap = "viridis_r" + +fig, ax = plt.subplots(figsize=(6, 4)) + +sc1 = ax.scatter(tsr1, runtime1,c = pitch1_deg, cmap=cmap, norm=norm, + alpha=0.7, s=35, marker="o") +sc2 = ax.scatter(tsr2, runtime2, c = pitch2_deg, cmap=cmap, norm=norm, + alpha=0.7, s=35, marker="v") + +ax.set_xlabel("TSR") +ax.set_ylabel("Average BEM Runtime") + +# one shared colorbar +sm = mpl.cm.ScalarMappable(norm=norm, cmap=cmap) +sm.set_array([]) # compatibility +cbar = fig.colorbar(sm, ax=ax, label="Pitch (deg)") + +# shape legend (independent of colormap) +shape_handles = [ + Line2D([0], [0], marker='o', linestyle='None', color='k', + markerfacecolor='gray', label='PS_Mode = 3'), + Line2D([0], [0], marker='v', linestyle='None', color='k', + markerfacecolor='gray', label='PS_Mode = 0'), +] +ax.legend(handles=shape_handles, title="Marker shape", loc="best") + +fig.tight_layout() +fig.savefig("time_vs_tsr_colored_by_pitch.png", dpi=200) +plt.close(fig) \ No newline at end of file diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 3e15483..20158a9 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -25,7 +25,9 @@ from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls - +# THIS RUN HAD: +# VS_ControlMode: 2 +# WE_Mode: 0 figdir = Path("fig") @@ -46,7 +48,6 @@ def change_control_param(param_key, param_value, template_yaml, bem, regenerate pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( temp_yaml, bem, regenerate = regenerate, save_control_file = save_control_file, - # n_jobs=1 ) return pitch_interp, tsr_interp, rated_rotor_speed @@ -96,8 +97,8 @@ def main(): # takes ~25min with 8 workers rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp, rosco_PS_Mode_3_rated_rotorspeed = get_rosco_control_interps( rosco_yaml_PS_Mode_3, bem, - # regenerate = False, save_control_file = "control_ps_3.csv") - regenerate = True, save_control_file = "control_ps_3.csv") + regenerate = False, save_control_file = "control_ps_3.csv") + # regenerate = True, save_control_file = "control_ps_3.csv") end = time.time() print(f"Time to make control CSV: {end - start}") @@ -221,7 +222,6 @@ def main(): ax1.set_ylabel("$C_T [-]$") ax1.set_title("$C_T$") ax1.grid(True) - ax1.legend() ax2.plot( wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", @@ -242,7 +242,6 @@ def main(): ax2.set_ylabel("$C_P [-]$") ax2.set_title("$C_P$") ax2.grid(True) - ax2.legend() ax3.plot( wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", @@ -264,7 +263,7 @@ def main(): ax3.set_ylabel("$Power [MW]$") ax3.set_title("$Power$") ax3.grid(True) - ax3.legend(loc = 'lower left') + ax3.legend(loc = 'lower right') plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) diff --git a/examples/example_08_floris_rosco2.py b/examples/example_08_floris_rosco2.py new file mode 100644 index 0000000..bbe3edb --- /dev/null +++ b/examples/example_08_floris_rosco2.py @@ -0,0 +1,307 @@ +# Python modules +import os +import matplotlib.pyplot as plt +import tempfile +from pathlib import Path +from ruamel.yaml import YAML +import numpy as np +import pandas as pd +import polars as pl +from scipy.interpolate import interp1d +import time + +# FLORIS modules +from floris import FlorisModel, TimeSeries + +# ROSCO toolbox modules +from rosco.toolbox import controller as ROSCO_controller +from rosco.toolbox import turbine as ROSCO_turbine +from rosco.toolbox.inputs.validation import load_rosco_yaml + +# MITRotor modules +from MITRotor.Momentum import UnifiedMomentumLUT +from MITRotor import BEM, BEMGeometry, IEA15MW +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp +from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls + +figdir = Path("fig") + +def change_control_param(param_key, param_value, template_yaml, bem, regenerate = False, save_control_file = "control.csv"): + yaml = YAML() + with tempfile.TemporaryDirectory() as tmpdir: + temp_yaml = Path(tmpdir) / "rosco_temp.yaml" + + with open(template_yaml) as f: + data = yaml.load(f) + + data["controller_params"][param_key] = param_value + + with open(temp_yaml, "w") as f: + yaml.dump(data, f) + + pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( + temp_yaml, bem, + regenerate = regenerate, save_control_file = save_control_file, + ) + return pitch_interp, tsr_interp, rated_rotor_speed + +def get_turbine_power_coefficent(fturbine, fmodel, wind_speeds): + rotor_area = np.pi * fturbine.bem_model.rotor.R**2 + floris_power = np.squeeze(fmodel.get_turbine_powers()) + floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3 * fturbine.eff_ratio) + return floris_Cp, floris_power / 1e6 # MW + +def main(): + # wind condtions + wind_speeds = np.linspace(3, 25, 25) + wind_dirs = np.full_like(wind_speeds, 270.0) + turbulence_intensity = np.zeros_like(wind_speeds) + time_series = TimeSeries( + wind_speeds=wind_speeds, + wind_directions=wind_dirs, + turbulence_intensities=turbulence_intensity, + ) + + # load example trajectories from ROSCO Paper Figure 2: + # Abbas, N. J., Zalkind, D. S., Pao, L., & Wright, A. (2022). + # A reference open-source controller for fixed and floating offshore wind turbines. + # Wind Energy Science, 7(1), 53-73. + abbas_pitch = pd.read_csv("examples/examples_in/IEA15_pitch.csv") # note that this is in degrees + abbas_tsr = pd.read_csv("examples/examples_in/IEA15_TSR.csv") + abbas_pitch_interp = interp1d(abbas_pitch["x"], abbas_pitch["y"], kind="linear", fill_value="extrapolate", bounds_error=False) + abbas_tsr_interp = interp1d(abbas_tsr["x"], abbas_tsr["y"], kind="linear", fill_value="extrapolate", bounds_error=False) + + # create new MITRotor BEM model with a LUT for UMM + print("Generating new LUT for BEM.") + cache_dir = Path("cache") + cache_dir.mkdir(exist_ok=True, parents=True) + cache_file = cache_dir / "lut.csv" + lut_model = UnifiedMomentumLUT( + cache_fn=cache_file, + regenerate=False, + LUT_Cts=np.linspace(-0.5,1.5,40), + LUT_yaws=np.linspace(0.0,40.0,40), + ) + print("LUT for BEM done generating. ") + bem = BEM(rotor = IEA15MW(), momentum_model = lut_model, geometry = BEMGeometry(Nr=10, Ntheta=20)) + + # Load IEA15MW ROSCO parameters to make controllers + start = time.time() + rosco_yaml_VS_1 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" + # takes ~25min with 8 workers + rosco_VS_1_pitch_interp, rosco_VS_1_tsr_interp, rosco_VS_1_rated_rotorspeed = get_rosco_control_interps( + rosco_yaml_VS_1, bem, + regenerate = False, save_control_file = "control_vs_1.csv") + # regenerate = True, save_control_file = "control_vs_1.csv") + end = time.time() + print(f"Time to make control CSV: {end - start}") + + rosco_VS_3_pitch_interp, rosco_VS_3_tsr_interp, rosco_VS_3_rated_rotorspeed = change_control_param( + "VS_ControlMode", 3, rosco_yaml_VS_1, bem, + regenerate = True, save_control_file = "control_vs_3.csv", + # regenerate = False, save_control_file = "control_vs_3.csv" + ) + + # Plot IEA15MW control from ROSCO paper, ROSOC control with VS_Control_Mode = 1, and ROSOC control withVS_Control_Mode = 3 + pitch_abbas = abbas_pitch_interp(wind_speeds) + pitch_ps0 = np.rad2deg(query_controls(rosco_VS_3_pitch_interp, wind_speeds, 0.0)) + pitch_ps3 = np.rad2deg(query_controls(rosco_VS_1_pitch_interp, wind_speeds, 0.0)) + + tsr_abbas = abbas_tsr_interp(wind_speeds) + tsr_ps0 = query_controls(rosco_VS_3_tsr_interp, wind_speeds, 0.0) + tsr_ps3 = query_controls(rosco_VS_1_tsr_interp, wind_speeds, 0.0) + + # Create figure + fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) + fig.suptitle(fr"Setpoint Trajectories") + # Plot pitch + ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO:VS_Control_Mode = 3", lw=3) + ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dashed") + ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") + + ax[0].set_xlabel("Wind Speed [m/s]") + ax[0].set_ylabel("Pitch [deg]") + ax[0].set_title("Pitch Schedule") + ax[0].grid(True) + + # Plot TSR + ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO:VS_Control_Mode = 3", lw=3) + ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dashed") + ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") + + ax[1].set_xlabel("Wind Speed [m/s]") + ax[1].set_ylabel("TSR [-]") + ax[1].set_title("Tip-Speed Ratio (TSR) Schedule") + ax[1].grid(True) + ax[1].legend() + + plt.savefig(figdir / "example_8_IEA15mw_controls.png", dpi=300) + + # make FLORIS turbines + floris_default_turbine = MITRotorTurbine( + bem_model = bem, + ) + + floris_abbas_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = abbas_pitch_interp, + pitch_rad = False, + tsr_interp = abbas_tsr_interp, + ) + + floris_VS_3_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = rosco_VS_3_pitch_interp, + pitch_rad = True, + tsr_interp = rosco_VS_3_tsr_interp, + rated_rotor_speed = rosco_VS_3_rated_rotorspeed, + ) + + floris_VS_1_turbine = MITRotorTurbine( + bem_model = bem, + pitch_interp = rosco_VS_1_pitch_interp, + pitch_rad = True, + tsr_interp = rosco_VS_1_tsr_interp, + rated_rotor_speed = rosco_VS_1_rated_rotorspeed, + ) + yaw = 0.0 # degrees + yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] + fmodel_default = FlorisModel("defaults") + fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_default.set_operation_model(floris_default_turbine) + fmodel_default.run() + Ct_default = fmodel_default.get_turbine_thrust_coefficients() + Cp_default, P_default = get_turbine_power_coefficent(floris_default_turbine, fmodel_default, wind_speeds) + + fmodel_abbas = FlorisModel("defaults") + fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_abbas.set_operation_model(floris_abbas_turbine) + fmodel_abbas.run() + Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() + Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) + + fmodel_VS_3 = FlorisModel("defaults") + fmodel_VS_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_VS_3.set_operation_model(floris_VS_3_turbine) + fmodel_VS_3.run() + Ct_VS_3 = fmodel_VS_3.get_turbine_thrust_coefficients() + Cp_VS_3, P_VS_3 = get_turbine_power_coefficent(floris_VS_3_turbine, fmodel_VS_3, wind_speeds) + + fmodel_VS_1 = FlorisModel("defaults") + fmodel_VS_1.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_VS_1.set_operation_model(floris_VS_1_turbine) + fmodel_VS_1.run() + Ct_VS_1 = fmodel_VS_1.get_turbine_thrust_coefficients() + Cp_VS_1, P_VS_1 = get_turbine_power_coefficent(floris_VS_1_turbine, fmodel_VS_1, wind_speeds) + + # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) + fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (16,4), constrained_layout=True) + fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = {yaw} for Different Control Strategies") + ax1.plot( + wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax1.plot( + wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax1.plot( + wind_speeds, Ct_VS_3, label="FLORIS+MITROTOR+ROSCO:VS_Control_Mode = 3", + lw=3, linestyle = "dashed", zorder = 1, + ) + ax1.plot(wind_speeds, Ct_VS_1, label="FLORIS+MITROTOR+ROSCO: VS_Control_Mode = 1", + lw=3, linestyle = "dotted", zorder = 1, + ) + ax1.set_xlabel("Wind Speed [m/s]") + ax1.set_ylabel("$C_T [-]$") + ax1.set_title("$C_T$") + ax1.grid(True) + + ax2.plot( + wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", + lw=3, linestyle = "solid", zorder = 1, + ) + ax2.plot( + wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax2.plot( + wind_speeds, Cp_VS_3, label="FLORIS + MITROTOR + ROSCO:VS_Control_Mode = 3", + lw=3, linestyle = "dashed", zorder = 1, + ) + ax2.plot(wind_speeds, Cp_VS_1, label="FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1", + lw=3, linestyle = "dotted", zorder = 1, + ) + ax2.set_xlabel("Wind Speed [m/s]") + ax2.set_ylabel("$C_P [-]$") + ax2.set_title("$C_P$") + ax2.grid(True) + + ax3.plot( + wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot( + wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot( + wind_speeds, P_VS_3, label="FLORIS + MITROTOR + ROSCO:VS_Control_Mode = 3", + lw=3, linestyle = "dashed", zorder = 1, + ) + ax3.plot(wind_speeds, P_VS_1, label="FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1", + lw=3, linestyle = "dotted", zorder = 1, + ) + ax3.axhline(y = 15, lw=3, linestyle = "dotted", zorder = 0, color = "k", label = "15MW") + ax3.set_xlabel("Wind Speed [m/s]") + ax3.set_ylabel("$Power [MW]$") + ax3.set_title("$Power$") + ax3.grid(True) + ax3.legend(loc = 'lower right') + + plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) + + # plot the difference in CT/CP curves for different yaw values + yaw_list = [0.0, 10.0, 20.0] # degrees + fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) + fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1") + for (i, yaw) in enumerate(yaw_list): + yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] + fmodel_VS_1 = FlorisModel("defaults") + fmodel_VS_1.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_VS_1.set_operation_model(floris_VS_1_turbine) + fmodel_VS_1.run() + ct = fmodel_VS_1.get_turbine_thrust_coefficients() + cp, p = get_turbine_power_coefficent(floris_VS_1_turbine, fmodel_VS_1, wind_speeds) + + ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + ax3.plot(wind_speeds, p, label=fr"Yaw = ${yaw}^\circ$", + lw=3, linestyle = "solid", zorder = 1, + ) + + ax1.set_xlabel("Wind Speed [m/s]") + ax1.set_ylabel("$C_T [-]$") + ax1.set_title("$C_T$") + ax1.grid(True) + + ax2.set_xlabel("Wind Speed [m/s]") + ax2.set_ylabel("$C_P [-]$") + ax2.set_title("$C_P$") + ax2.grid(True) + + ax3.axhline(y = 15, lw=3, linestyle = "dotted", zorder = 0, color = "k", label = "15MW") + ax3.set_xlabel("Wind Speed [m/s]") + ax3.set_ylabel("$Power [MW]$") + ax3.set_title("$Power$") + ax3.grid(True) + ax3.legend() + plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) + + +if __name__ == "__main__": + main() \ No newline at end of file From c30aa3bfb40efa01653afc1658c18beeaf9b6b96 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 11:14:52 -0400 Subject: [PATCH 33/50] Add access to x0 --- MITRotor/BEMSolver.py | 5 +++-- MITRotor/Momentum.py | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/MITRotor/BEMSolver.py b/MITRotor/BEMSolver.py index 87f64d6..61fe54c 100644 --- a/MITRotor/BEMSolver.py +++ b/MITRotor/BEMSolver.py @@ -46,6 +46,7 @@ class BEMSolution: v4: float tilt: float = 0.0 w4: float = 0 + x0: float = 0 def a(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.an, grid) @@ -246,7 +247,7 @@ def post_process(self, result: FixedPointIterationResult, pitch, tsr, yaw = 0, U aero_props = self.aerodynamic_model(an, aprime, pitch, tsr, yaw, self.rotor, self.geometry, U, wdir, tilt = tilt) aero_props.F = self.tiploss_model(aero_props, pitch, tsr, yaw, self.rotor, self.geometry, tilt = tilt) avg_Ct = average(self.geometry, aero_props.C_x) - u4,v4,w4 = self.momentum_model.compute_initial_wake_velocities(avg_Ct, yaw, tilt = tilt) + u4,v4,w4,x0 = self.momentum_model.compute_initial_wake_velocities_and_x0(avg_Ct, yaw, tilt = tilt) if self.scalar_inputs: # if all setpoints were scalars # return single values as scalars @@ -261,4 +262,4 @@ def post_process(self, result: FixedPointIterationResult, pitch, tsr, yaw = 0, U if isinstance(value, np.ndarray): setattr(aero_props, key, np.squeeze(value)) - return BEMSolution(pitch, tsr, yaw, aero_props, self.geometry, result.converged, result.niter, u4, v4, tilt = tilt, w4 = w4) + return BEMSolution(pitch, tsr, yaw, aero_props, self.geometry, result.converged, result.niter, u4, v4, tilt = tilt, w4 = w4, x0 = x0) diff --git a/MITRotor/Momentum.py b/MITRotor/Momentum.py index 2f114ff..cb4bb4e 100644 --- a/MITRotor/Momentum.py +++ b/MITRotor/Momentum.py @@ -292,6 +292,11 @@ def compute_initial_wake_velocities(self, Cx: ArrayLike, yaw: float = 0.0, tilt: sol = self.model_Ct(Cx, yaw = yaw, tilt = tilt) return sol.u4, sol.v4, sol.w4 + def compute_initial_wake_velocities_and_x0(self, Cx: ArrayLike, yaw: float = 0.0, tilt: float = 0.0) -> ArrayLike: + sol = self.model_Ct(Cx, yaw = yaw, tilt = tilt) + return sol.u4, sol.v4, sol.w4, sol.x0 + + # Look-up table for unified model def func_Ct(x, beta, cached) -> dict: From dd3eb7ea8a870dd63284df747b4ba3139dc7eb6e Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 11:24:19 -0400 Subject: [PATCH 34/50] remove comma --- MITRotor/FlorisInterface/FlorisInterface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index b16f988..5226101 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -164,7 +164,7 @@ def _update_solution(self, self._a[:, tindex] = bem_sol.a() self._Ct[:, tindex] = bem_sol.Ct() # get near wake velocities - self._u4 = bem_sol.u4, + self._u4 = bem_sol.u4 self._v4 = bem_sol.v4 self._w4 = bem_sol.w4 self._x0 = bem_sol.x0 From 733326bc61f9b82239134b9f2182521ba3fdadb5 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 11:28:23 -0400 Subject: [PATCH 35/50] index near wake values --- MITRotor/FlorisInterface/FlorisInterface.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 5226101..c224a3b 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -164,10 +164,10 @@ def _update_solution(self, self._a[:, tindex] = bem_sol.a() self._Ct[:, tindex] = bem_sol.Ct() # get near wake velocities - self._u4 = bem_sol.u4 - self._v4 = bem_sol.v4 - self._w4 = bem_sol.w4 - self._x0 = bem_sol.x0 + self._u4[:, tindex] = bem_sol.u4 + self._v4[:, tindex] = bem_sol.v4 + self._w4[:, tindex] = bem_sol.w4 + self._x0[:, tindex] = bem_sol.x0 # compute power self._power[:, tindex] = ( 0.5 * bem_sol.Cp() * air_density * rotor_area From 993a20ce1f817be7b96303cc46b30836f8e662f1 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 16:18:40 -0400 Subject: [PATCH 36/50] fix floris interface tests --- MITRotor/Momentum.py | 7 +++++-- tests/test_floris_interface.py | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/MITRotor/Momentum.py b/MITRotor/Momentum.py index cb4bb4e..50f1abd 100644 --- a/MITRotor/Momentum.py +++ b/MITRotor/Momentum.py @@ -47,6 +47,11 @@ def compute_induction(self, Cx: ArrayLike, yaw: float = 0, tilt:float = 0) -> Ar def compute_initial_wake_velocities(self, Ct: float, yaw: float = 0, tilt: float = 0.0) -> ArrayLike: ... + def compute_initial_wake_velocities_and_x0( + self, Ct: float, yaw: float = 0, tilt: float = 0.0 + ) -> ArrayLike: + return (*self.compute_initial_wake_velocities(Ct, yaw, tilt), None) + def _func_rotor( self, @@ -161,8 +166,6 @@ def compute_initial_wake_velocities(self, Ct: float, yaw: float, tilt: float = 0 w4 = 0.0 return u4, v4, w4 - - class MadsenMomentum(MomentumModel): """ Madsen Momentum model based on 2020 paper: diff --git a/tests/test_floris_interface.py b/tests/test_floris_interface.py index ad109ad..7c0e8d5 100644 --- a/tests/test_floris_interface.py +++ b/tests/test_floris_interface.py @@ -17,13 +17,14 @@ def test_pitch_tsr_interpolation(): validation_csv = os.path.abspath(os.path.join(module_dir, "..", "MITRotor", "FlorisInterface", "IEA_15mw_rotor.csv")) df = pl.read_csv(validation_csv) wind_data = df["Wind [m/s]"].to_numpy() - pitch_data = df["Pitch [deg]"].to_numpy() + pitch_deg_data = df["Pitch [deg]"].to_numpy() + pitch_rad_data = np.deg2rad(pitch_deg_data) tip_speed_data = df["Tip Speed [m/s]"].to_numpy() tsr_data = tip_speed_data / wind_data # interpolator reproduces raw data assert_allclose(tsr_interp(wind_data), tsr_data, rtol=1e-12, atol=1e-12) - assert_allclose(pitch_interp(wind_data), pitch_data, rtol=1e-12, atol=1e-12) + assert_allclose(pitch_interp(wind_data), pitch_rad_data, rtol=1e-12, atol=1e-12) # reasonable values x_interp_vals = np.linspace(0.0, 25.0, 100) @@ -46,9 +47,9 @@ def compute_mitrotor_cp_ct_a(wind_speeds, yaw_deg = 0.0, tilt_deg = 0.0): Ct = np.empty(n) a = np.empty(n) for i, ws in enumerate(wind_speeds): - pitch = np.deg2rad(pitch_interp(ws)) + pitch_rad = pitch_interp(ws) tsr = tsr_interp(ws) - sol = bem_model(pitch, tsr, yaw=np.deg2rad(yaw_deg), tilt = np.deg2rad(tilt_deg)) + sol = bem_model(pitch_rad, tsr, yaw=np.deg2rad(yaw_deg), tilt = np.deg2rad(tilt_deg)) Ct[i] = sol.Ct() a[i] = sol.a() From 2c5acacd57102bd2d69d1e2a206eb61cacfd6e6f Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 16:38:07 -0400 Subject: [PATCH 37/50] Fix example 6 cp calc to include eff ratio --- MITRotor/FlorisInterface/FlorisInterface.py | 13 ++++------ MITRotor/FlorisInterface/FlorisUtilities.py | 0 examples/example_06_floris_integration.py | 27 ++++++--------------- 3 files changed, 13 insertions(+), 27 deletions(-) create mode 100644 MITRotor/FlorisInterface/FlorisUtilities.py diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index c224a3b..97215e8 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -35,8 +35,7 @@ def default_pitch_interp(): pitch_file = os.path.join(module_dir, "IEA_15mw_rotor.csv") df = pl.read_csv(pitch_file) wind_table = df["Wind [m/s]"].to_numpy() - pitch_table = np.deg2rad(df["Pitch [deg]"]) - # TODO: should fill_value be extrapolate? + pitch_table = np.deg2rad(df["Pitch [deg]"]) # interpolator takes in radians! return interp1d(wind_table, pitch_table, kind="linear", fill_value="extrapolate", bounds_error=False) # default 1D tsr vs windspeed interpolater if none provided by user @@ -48,7 +47,6 @@ def default_tsr_interp(): wind_table = df["Wind [m/s]"].to_numpy() tip_speed_table = df["Tip Speed [m/s]"].to_numpy() tsr_table = tip_speed_table / wind_table - # TODO: should fill_value be extrapolate? return interp1d(wind_table, tsr_table, kind="linear", fill_value="extrapolate", bounds_error=False) @define @@ -79,7 +77,7 @@ class MITRotorTurbine(BaseOperationModel): # create interp objects based on pitch and tsr csvs pitch_interp = field(init = True, factory = default_pitch_interp, type = Optional[InterpLike], repr = False) - pitch_rad = field(init = True, default = True, type = bool) + pitch_rad = field(init = True, default = True, type = bool) # set if interpolater takes in radians (True) or degrees (False) tsr_interp = field(init = True, factory = default_tsr_interp, type = Optional[InterpLike], repr=False) rated_rotor_speed = field(init = True, default = None, type = Optional[float]) # [rad/s] @@ -110,11 +108,10 @@ def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_an def _update_solution(self, velocities: NDArrayFloat, air_density: float, - yaw_angles: NDArrayFloat, - tilt_angles: NDArrayFloat, + yaw_angles: NDArrayFloat, # input in degrees + tilt_angles: NDArrayFloat, # input in degrees average_method: str = "cubic-mean", cubature_weights: Optional[NDArrayFloat] = None, - power_thrust_table: Optional[dict] = None, **_, ): # create cache key for current inputs @@ -153,7 +150,7 @@ def _update_solution(self, self.tsr_interp, rotor_average_velocities, eff_yaw, kind = "tsr", rated_rotor_speed = self.rated_rotor_speed, rotor_radius = self.bem_model.rotor.R, ) - if not self.pitch_rad: + if not self.pitch_rad: # make sure input to MITRotor BEM in in radians pitch = np.deg2rad(pitch) # solve BEM for setpoints from control curves diff --git a/MITRotor/FlorisInterface/FlorisUtilities.py b/MITRotor/FlorisInterface/FlorisUtilities.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/example_06_floris_integration.py b/examples/example_06_floris_integration.py index 07f8c32..e0715a7 100644 --- a/examples/example_06_floris_integration.py +++ b/examples/example_06_floris_integration.py @@ -129,20 +129,6 @@ mit_Cp_annulus_umm = mit_sols_annulus_umm.Cp() print("MITRotor UMM-BEM Annulus-Averaged: " + str(mit_annulus_umm_end - mit_annulus_umm_start) + " seconds") -# solve UMM-BEM though MITRotor - sector averaged -# bem_sector_umm = BEM( -# rotor=IEA15MW(), -# momentum_model=UnifiedMomentum(averaging="sector"), -# geometry=BEMGeometry(Nr=10, Ntheta=20), -# tiploss_model=NoTipLoss(), -# ) -# mit_sector_umm_start = time.time() -# mit_sols_sector_umm = bem_sector_umm(pitch=pitches, tsr=tsrs, yaw=yaws, tilt=tilts) -# mit_sector_umm_end = time.time() -# mit_Ct_sector_umm = mit_sols_sector_umm.Ct() -# mit_Cp_sector_umm = mit_sols_sector_umm.Cp() -# print("MITRotor UMM-BEM Sector-Averaged: " + str(mit_sector_umm_end - mit_sector_umm_start) + " seconds") - # solve UMM-BEM with LUT though MITRotor - annulus averaged print("Making LUT!") bem_annulus_umm_LUT = BEM( @@ -164,16 +150,19 @@ wind_directions=wind_dirs, turbulence_intensities=turbulence_intensity, ) +floris_rotor_model = MITRotorTurbine() +rotor_area = np.pi * bem_rotor_umm.rotor.R**2 +cp_calc_denominator = (0.5 * floris_air_density * rotor_area * (wind_speeds)**3 * floris_rotor_model.eff_ratio) + fmodel_rotor_umm = FlorisModel("defaults") fmodel_rotor_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) -fmodel_rotor_umm.set_operation_model(MITRotorTurbine()) # default bem_model uses rotor-averaging +fmodel_rotor_umm.set_operation_model(floris_rotor_model) # default bem_model uses rotor-averaging floris_rotor_umm_start = time.time() fmodel_rotor_umm.run() floris_rotor_umm_end = time.time() floris_Ct_rotor_umm = fmodel_rotor_umm.get_turbine_thrust_coefficients() -rotor_area = np.pi * bem_rotor_umm.rotor.R**2 floris_power_rotor_umm = np.squeeze(fmodel_rotor_umm.get_turbine_powers()) -floris_Cp_rotor_umm = floris_power_rotor_umm / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +floris_Cp_rotor_umm = floris_power_rotor_umm / cp_calc_denominator print("FLORIS UMM-BEM Rotor-Averaged: " + str(floris_rotor_umm_end - floris_rotor_umm_start) + " seconds") # solve FLORIS with UMM-BEM though MITRotor - annulus averaged @@ -185,7 +174,7 @@ floris_annulus_umm_end = time.time() floris_Ct_annulus_umm = fmodel_annulus_umm.get_turbine_thrust_coefficients() floris_power_annulus_umm = np.squeeze(fmodel_annulus_umm.get_turbine_powers()) -floris_Cp_annulus_umm = floris_power_annulus_umm / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) # TODO: account for eff_ratio +floris_Cp_annulus_umm = floris_power_annulus_umm / cp_calc_denominator print("FLORIS UMM-BEM Annulus-Averaged: " + str(floris_annulus_umm_end - floris_annulus_umm_start) + " seconds") # solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged @@ -197,7 +186,7 @@ floris_annulus_umm_LUT_end = time.time() floris_Ct_annulus_umm_LUT = fmodel_annulus_umm_LUT.get_turbine_thrust_coefficients() floris_power_annulus_umm_LUT = np.squeeze(fmodel_annulus_umm_LUT.get_turbine_powers()) -floris_Cp_annulus_umm_LUT = floris_power_annulus_umm_LUT / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) +floris_Cp_annulus_umm_LUT = floris_power_annulus_umm_LUT / cp_calc_denominator print("FLORIS UMM-BEM LUT Annulus-Averaged: " + str(floris_annulus_umm_LUT_end - floris_annulus_umm_LUT_start) + " seconds") # Presentation-friendly typography From 3b5d5911cfc7674ea1369f14645735c7c7a210fd Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Thu, 30 Jul 2026 17:20:31 -0400 Subject: [PATCH 38/50] Finish cleaning up FLORIS examples --- examples/example_06_floris_integration.py | 11 +-- examples/example_07_LUT_timing.py | 101 ++++++++++++++++++++-- 2 files changed, 96 insertions(+), 16 deletions(-) diff --git a/examples/example_06_floris_integration.py b/examples/example_06_floris_integration.py index e0715a7..9df7e71 100644 --- a/examples/example_06_floris_integration.py +++ b/examples/example_06_floris_integration.py @@ -3,15 +3,7 @@ import polars as pl from pathlib import Path import time -import warnings - -warnings.filterwarnings("ignore", category=RuntimeWarning) # JUST FOR NOW - - import matplotlib.pyplot as plt -from matplotlib import cm -from matplotlib.colors import Normalize -from matplotlib.cm import ScalarMappable # Floris imports from floris import FlorisModel, TimeSeries @@ -24,6 +16,9 @@ from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM +# Example shows that MITRotor rotor values are equivalent to FLORIS rotor values when MITRotor is +# set as the rotor model using the `set_operation_model` function. + figdir = Path("fig") floris_air_density = 1.225 # ------------------ run basic case -------------------------------------------------------- diff --git a/examples/example_07_LUT_timing.py b/examples/example_07_LUT_timing.py index 988b814..19c0428 100644 --- a/examples/example_07_LUT_timing.py +++ b/examples/example_07_LUT_timing.py @@ -5,24 +5,36 @@ from MITRotor import BEM, IEA15MW, BEMGeometry import pandas as pd import time +import matplotlib.pyplot as plt # Floris imports from floris import FlorisModel, TimeSeries from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory +figdir = Path("fig") +floris_air_density = 1.225 + bem_rotor_umm = default_bem_factory() +bem_rotor_umm_LUT = BEM( + rotor=IEA15MW(), + momentum_model=UnifiedMomentumLUT(averaging="rotor", cache_fn = Path("cache")/ "rotor_lut.csv"), + geometry=BEMGeometry(Nr=10, Ntheta=20), + tiploss_model=NoTipLoss(), +) bem_annulus_umm_LUT = BEM( rotor=IEA15MW(), - momentum_model=UnifiedMomentumLUT(averaging="annulus", cache_fn = Path("cache")/ "lut.csv"), + momentum_model=UnifiedMomentumLUT(averaging="annulus", cache_fn = Path("cache")/ "annulus_lut.csv"), geometry=BEMGeometry(Nr=10, Ntheta=20), tiploss_model=NoTipLoss(), ) rotor_area = np.pi * bem_rotor_umm.rotor.R**2 bem_rotor_times = [] +bem_rotor_LUT_times = [] bem_annulus_LUT_times = [] wind_speeds_all = [] bem_rotor_values = [] +bem_rotor_LUT_values = [] bem_annulus_LUT_values = [] ns = [5 * i for i in range(1, 21)] for n in ns: @@ -39,32 +51,47 @@ wind_directions=wind_dirs, turbulence_intensities=turbulence_intensity, ) - + # solve FLORIS with UMM-BEM though MITRotor - rotor averaged fmodel_rotor_umm = FlorisModel("defaults") fmodel_rotor_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) - fmodel_rotor_umm.set_operation_model(MITRotorTurbine(bem_model = bem_rotor_umm)) # default bem_model uses rotor-averaging + floris_rotor_model = MITRotorTurbine(bem_model = bem_rotor_umm) + fmodel_rotor_umm.set_operation_model(floris_rotor_model) # default bem_model uses rotor-averaging floris_rotor_umm_start = time.time() fmodel_rotor_umm.run() floris_rotor_umm_end = time.time() dt_rotor = floris_rotor_umm_end - floris_rotor_umm_start print("FLORIS UMM-BEM Rotor-Averaged: " + str(dt_rotor) + " seconds") bem_rotor_times.append(dt_rotor) - floris_Cp_rotor_umm = np.squeeze(fmodel_rotor_umm.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) - bem_rotor_values.extend( - np.squeeze(floris_Cp_rotor_umm) + cp_calc_denominator = (0.5 * floris_air_density * rotor_area * (wind_speeds)**3 * floris_rotor_model.eff_ratio) + floris_Cp_rotor_umm = np.squeeze(fmodel_rotor_umm.get_turbine_powers()) / cp_calc_denominator + bem_rotor_values.extend(np.squeeze(floris_Cp_rotor_umm)) + + # solve FLORIS with UMM-BEM with LUT though MITRotor - rotor averaged + fmodel_rotor_umm_LUT = FlorisModel("defaults") + fmodel_rotor_umm_LUT.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) + fmodel_rotor_umm_LUT.set_operation_model(MITRotorTurbine(bem_model = bem_rotor_umm_LUT)) + floris_rotor_umm_LUT_start = time.time() + fmodel_rotor_umm_LUT.run() + floris_rotor_umm_LUT_end = time.time() + dt_rotor_LUT = floris_rotor_umm_LUT_end - floris_rotor_umm_LUT_start + print("FLORIS UMM-BEM LUT Rotor-Averaged: " + str(dt_rotor_LUT) + " seconds") + bem_rotor_LUT_times.append(dt_rotor_LUT) + floris_Cp_rotor_umm_LUT = np.squeeze(fmodel_rotor_umm_LUT.get_turbine_powers()) / cp_calc_denominator + bem_rotor_LUT_values.extend( + np.squeeze(floris_Cp_rotor_umm_LUT) ) # solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged fmodel_annulus_umm_LUT = FlorisModel("defaults") fmodel_annulus_umm_LUT.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) - fmodel_annulus_umm_LUT.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_umm_LUT)) # default bem_model uses rotor-averaging + fmodel_annulus_umm_LUT.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_umm_LUT)) floris_annulus_umm_LUT_start = time.time() fmodel_annulus_umm_LUT.run() floris_annulus_umm_LUT_end = time.time() dt_annulus_LUT = floris_annulus_umm_LUT_end - floris_annulus_umm_LUT_start print("FLORIS UMM-BEM LUT Annulus-Averaged: " + str(dt_annulus_LUT) + " seconds") bem_annulus_LUT_times.append(dt_annulus_LUT) - floris_Cp_annulus_umm_LUT = np.squeeze(fmodel_annulus_umm_LUT.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) + floris_Cp_annulus_umm_LUT = np.squeeze(fmodel_annulus_umm_LUT.get_turbine_powers()) / cp_calc_denominator bem_annulus_LUT_values.extend( np.squeeze(floris_Cp_annulus_umm_LUT) ) @@ -81,6 +108,14 @@ "vectorized": vectorized }) +for n, dt in zip(ns, bem_rotor_LUT_times): + rows.append({ + "n_wind_speeds": n, + "runtime_seconds": dt, + "model": "rotor_lut", + "vectorized": vectorized + }) + for n, dt in zip(ns, bem_annulus_LUT_times): rows.append({ "n_wind_speeds": n, @@ -98,6 +133,20 @@ else: df.to_csv(csv_path, index=False) +# ------------------------------------------------------------------ +# Plot timings +# ------------------------------------------------------------------ +plt.figure() +plt.plot(ns, bem_rotor_times, "o-", label="Rotor-averaged UMM") +plt.plot(ns,bem_rotor_LUT_times, "v-",label="Rotor-averaged UMM with LUT") +plt.plot(ns,bem_annulus_LUT_times, "s-",label="Annulus-averaged UMM with LUT") +plt.xlabel("Number of wind speeds") +plt.ylabel("Runtime (s)") +plt.yscale("log") +plt.title("FLORIS Runtime Comparison") +plt.legend() +plt.savefig(figdir / "example_7_floris_runtimes.png", dpi=300) + # make values CSV rows = [] # Rotor @@ -109,6 +158,15 @@ "vectorized": vectorized }) +# Rotor LUT +for wind, val in zip(wind_speeds_all, bem_rotor_LUT_values): + rows.append({ + "wind_speed": wind, + "power": val, + "model": "rotor_lut", + "vectorized": vectorized + }) + # Annulus LUT for wind, val in zip(wind_speeds_all, bem_annulus_LUT_values): rows.append({ @@ -126,3 +184,30 @@ df.to_csv(csv_path, mode="a", header=False, index=False) else: df.to_csv(csv_path, index=False) + +import matplotlib.pyplot as plt + +# ------------------------------------------------------------------ +# Plot results +# ------------------------------------------------------------------ +# Sort by wind speed for plotting +sort_idx = np.argsort(wind_speeds_all) + +wind_speeds_plot = np.array(wind_speeds_all)[sort_idx] +bem_rotor_plot = np.array(bem_rotor_values)[sort_idx] +bem_rotor_LUT_plot = np.array(bem_rotor_LUT_values)[sort_idx] +bem_annulus_LUT_plot = np.array(bem_annulus_LUT_values)[sort_idx] + +plt.figure() + +plt.plot(wind_speeds_plot, bem_rotor_plot, label="Rotor-averaged UMM", linestyle="-", linewidth=3) +plt.plot(wind_speeds_plot, bem_rotor_LUT_plot, label="Rotor-averaged UMM with LUT", linestyle="--", linewidth=3) +plt.plot(wind_speeds_plot, bem_annulus_LUT_plot, label="Annulus-averaged UMM with LUT", linestyle=":", linewidth=3) + +plt.xlabel("Wind speed (m/s)") +plt.ylabel(r"$C_P$") +plt.title("Power Coefficient Comparison") +plt.grid(True) +plt.legend() +plt.tight_layout() +plt.savefig(figdir / "example_7_floris_cp_vals.png", dpi=300) From 871d2cb9ea5449f4e6af1e12defbfd81abd3c73f Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 31 Jul 2026 09:07:57 -0400 Subject: [PATCH 39/50] Cleaned up ROSCO interface --- MITRotor/FlorisInterface/FlorisInterface.py | 2 +- MITRotor/FlorisInterface/FlorisUtilities.py | 0 .../FlorisInterface/InterfaceUtilities.py | 520 ++++++++++++++ MITRotor/FlorisInterface/ROSCOInterface.py | 664 +++--------------- examples/example_08_floris_rosco.py | 3 +- examples/example_08_floris_rosco2.py | 4 +- poetry.lock | 4 +- 7 files changed, 628 insertions(+), 569 deletions(-) delete mode 100644 MITRotor/FlorisInterface/FlorisUtilities.py create mode 100644 MITRotor/FlorisInterface/InterfaceUtilities.py diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 97215e8..f08392d 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -15,7 +15,7 @@ from MITRotor.Geometry import BEMGeometry from MITRotor.TipLoss import NoTipLoss from MITRotor.BEMSolver import BEM -from MITRotor.FlorisInterface.ROSCOInterface import query_controls +from MITRotor.FlorisInterface.InterfaceUtilities import query_controls from UnifiedMomentumModel.Utilities.Geometry import calc_eff_yaw InterpLike = Union[interp1d, RegularGridInterpolator, Callable] diff --git a/MITRotor/FlorisInterface/FlorisUtilities.py b/MITRotor/FlorisInterface/FlorisUtilities.py deleted file mode 100644 index e69de29..0000000 diff --git a/MITRotor/FlorisInterface/InterfaceUtilities.py b/MITRotor/FlorisInterface/InterfaceUtilities.py new file mode 100644 index 0000000..a954fe5 --- /dev/null +++ b/MITRotor/FlorisInterface/InterfaceUtilities.py @@ -0,0 +1,520 @@ +from collections import deque +from contextlib import contextmanager +from ctypes import cdll, POINTER, c_float, c_int32, c_char_p, create_string_buffer +from dataclasses import dataclass +import numpy as np +import sys +from scipy.interpolate import RegularGridInterpolator +import os +import warnings +from joblib import Parallel, delayed +from tqdm.auto import tqdm +from tqdm_joblib import tqdm_joblib +from pathlib import Path + +# ROSCO imports +from rosco.toolbox import control_interface as ROSCO_ci + +# ----------------------------- +# Control Interpolator Helpers +# ----------------------------- +def query_controls( + interp, + ws, + yaw_rad, + *, + kind="generic", # "pitch" or "tsr" + rated_rotor_speed=None, # rad/s (for 1D tsr scheme) + rotor_radius=None, # m (required if rated_rotor_speed is set) +): + """ + Gets TRS or pitch values for given wind speeds and yaw from interpolator + + Supports: + - 2D RegularGridInterpolator: interp(ws, yaw) + - 1D interp1d/callable: interp(ws), yaw ignored (warn if |yaw| > 0) + + For 1D TSR and rated_rotor_speed provided: + applies simple above-rated cap via omega = tsr*ws/R. + """ + ws_arr = np.asarray(ws, dtype=float) + yaw_arr = np.asarray(yaw_rad, dtype=float) + ws_b, yaw_b = np.broadcast_arrays(ws_arr, yaw_arr) + + # 2D LUT path + if isinstance(interp, RegularGridInterpolator) and len(interp.grid) == 2: + pts = np.column_stack((ws_b.ravel(), yaw_b.ravel())) + vals = np.asarray(interp(pts)).reshape(ws_b.shape) + else: # 1D legacy path + vals = np.asarray(interp(ws_b)).reshape(ws_b.shape) + # warning if non-zero yaw values + if np.any(np.abs(yaw_b) > 0): + warnings.warn( + "Using 1D control curve with nonzero yaw/tilt; yaw/tilt is ignored for lookup.", + UserWarning, + ) + # basic rated rotor speed tracking for above rated conditions + if kind == "tsr": + if rated_rotor_speed is not None: + if rotor_radius is None: + raise ValueError("rotor_radius is required when rated_rotor_speed is set.") + omega_lookup = vals * ws_b / np.maximum(rotor_radius, 1e-12) + tsr_from_rated = rated_rotor_speed * rotor_radius / np.maximum(ws_b, 1e-6) + vals = np.where(omega_lookup <= rated_rotor_speed, vals, tsr_from_rated) + vals = np.maximum(vals, 0.0) + + return float(vals) if vals.shape == () else vals + +def load_control_interps_from_csv(csv_path): + """ + Load wind/yaw control LUT CSV and return 2D interpolators. + + Expected CSV columns: + wind_speed_mps, yaw_rad, pitch_rad, tsr, gen_power + """ + data = np.genfromtxt(csv_path, delimiter=",", names=True) + + ws = np.asarray(data["wind_speed_mps"], dtype=float) + yaw = np.asarray(data["yaw_rad"], dtype=float) + pitch = np.asarray(data["pitch_rad"], dtype=float) + tsr = np.asarray(data["tsr"], dtype=float) + + v_grid = np.unique(ws) + yaw_grid = np.unique(yaw) + + # sort cols by (ws, yaw), then reshape into [n_ws, n_yaw] + order = np.lexsort((yaw, ws)) + n_ws, n_yaw = len(v_grid), len(yaw_grid) + + pitch_tbl = pitch[order].reshape(n_ws, n_yaw) + tsr_tbl = tsr[order].reshape(n_ws, n_yaw) + + pitch_interp = RegularGridInterpolator( + (v_grid, yaw_grid), pitch_tbl, + method="linear", bounds_error=False, fill_value=None + ) + tsr_interp = RegularGridInterpolator( + (v_grid, yaw_grid), tsr_tbl, + method="linear", bounds_error=False, fill_value=None + ) + + return pitch_interp, tsr_interp + +def save_control_interps_to_csv(save_control_file, v_grid, yaw_grid_rad, pitch_tbl, tsr_tbl, power_tbl): + if save_control_file is not None: + save_control_file = Path(save_control_file) + save_control_file.parent.mkdir(parents=True, exist_ok=True) + + vv, yy = np.meshgrid(v_grid, yaw_grid_rad, indexing="ij") + data = np.column_stack([ + vv.ravel(), # wind_speed_mps + yy.ravel(), # yaw_rad + pitch_tbl.ravel(), # pitch_rad + tsr_tbl.ravel(), # tsr + power_tbl.ravel(), # generated power + ]) + + header = "wind_speed_mps,yaw_rad,pitch_rad,tsr,gen_power" + np.savetxt(save_control_file, data, delimiter=",", header=header, comments="") + +# ----------------------------- +# Parallelization Helpers +# ----------------------------- +def get_num_jobs(n_jobs, n_wind): +# Determine effective n_jobs + if n_jobs is None: + n_jobs_eff = 1 + elif n_jobs == -1: + n_jobs_eff = min(os.cpu_count() or 1, n_wind) + else: + n_jobs_eff = max(1, min(int(n_jobs), n_wind)) + return n_jobs_eff + +def run_yaw_row_sim(v_grid, yaw_grid_rad, yaw_row_func, n_jobs): + # Calculate total number of cases + n_wind = len(v_grid) + n_yaw = len(yaw_grid_rad) + total_cases = n_wind * n_yaw + + # Determine effective n_jobs + n_jobs_eff = get_num_jobs(n_jobs, n_wind) + + # Run parallel (fallback to serial on failure, e.g., pickling issue) + print( + f"Starting control LUT sweep: {n_yaw} yaw tasks " + f"({total_cases} wind-yaw cases), using {n_jobs_eff} worker process(es)." + ) + + def _run_serial(desc): + out = [] + for i, yaw_rad in enumerate(tqdm(yaw_grid_rad, total=n_wind, desc=desc, dynamic_ncols=True)): + out.append(yaw_row_func(i, yaw_rad)) + return out + + cols = None + if n_jobs_eff > 1: + bar = tqdm(total=n_yaw, desc="Control LUT sweep (wind cols)", dynamic_ncols=True) + try: + with tqdm_joblib(bar): + cols = Parallel(n_jobs=n_jobs_eff, backend="loky", verbose=0, batch_size=1)( + delayed(yaw_row_func)(i, yaw_rad) + for i, yaw_rad in enumerate(yaw_grid_rad) + ) + except Exception as e: + warnings.warn( + f"Parallel execution failed ({type(e).__name__}: {e}). " + "Falling back to serial execution.", + RuntimeWarning, + ) + finally: + bar.close() + if cols is None: + desc = "Control LUT sweep (serial fallback)" if n_jobs_eff > 1 else "Control LUT sweep (serial)" + cols = _run_serial(desc) + + return cols + +# ----------------------------- +# Controller Interface -> child of ROSCOS's ControllerInterface +# ----------------------------- +class WarmStartControllerInterface(ROSCO_ci.ControllerInterface): + """ + ROSCO controller interface with configurable warm-start initial conditions. + + This subclass overrides the default `ControllerInterface` initialization so + the first DISCON call (`iStatus=0`) is seeded with user-provided initial + wind speed, rotor/generator speeds, pitch, torque, and nacelle IMU angle, + instead of hard-coded defaults. + + Notes + ----- + - This is useful for steady-state sweeps, where reducing startup transients + improves convergence speed and robustness. + - Units are expected to match ROSCO avrSWAP channel conventions. + """ + + def __init__( + self, + lib_name, + param_filename="DISCON.IN", + init_ws=10.0, # m/s + init_rot_speed=1.0, # rad/s + init_gen_speed=1.0, # rad/s + init_pitch_deg=0.0, # deg + init_torque=0.0, # Nm + init_nac_imu=0.0, # rad + **kwargs + ): + """ + Initialize warm-start settings and construct the ROSCO controller interface. + + Parameters + ---------- + lib_name : str + Path to the ROSCO dynamic library (.dll/.so/.dylib). + param_filename : str, optional + Path to DISCON input file, by default "DISCON.IN". + init_ws : float, optional + Initial wind speed used during DISCON init, in m/s. + init_rot_speed : float, optional + Initial low-speed shaft rotor speed, in rad/s. + init_gen_speed : float, optional + Initial generator speed (high-speed shaft), in rad/s. + init_pitch_deg : float, optional + Initial collective blade pitch, in degrees. + init_torque : float, optional + Initial generator torque, in Nm. + init_nac_imu : float, optional + Initial nacelle IMU angle/state, in radians. + **kwargs + Additional keyword arguments forwarded to + `ROSCO_ci.ControllerInterface` (e.g., `DT`, `sim_name`, etc.). + """ + # Set starting conditions + self.init_ws = float(init_ws) + self.init_rot_speed = float(init_rot_speed) + self.init_gen_speed = float(init_gen_speed) + self.init_torque = float(init_torque) + self.init_nac_imu = float(init_nac_imu) + + # Parent uses self.pitch for initial blade pitch + super().__init__( + lib_name, + param_filename=param_filename, + pitch=init_pitch_deg, + **kwargs + ) + + def init_discon(self): + """ + Initialize DISCON with warm-start avrSWAP values. + + This method allocates and populates the avrSWAP array, sets the first-call + status (`iStatus=0`), invokes DISCON once to initialize internal ROSCO states, + then switches to normal run mode (`iStatus=1`) for subsequent calls. + + Raises + ------ + ValueError + If ROSCO returns a negative `aviFAIL` error code during initialization. + """ + self.torque = self.init_torque + + # Load library + allocate swap + self.discon = cdll.LoadLibrary(self.lib_name) + self.avrSWAP = np.zeros(self.avr_size) + + # Required channels + self.avrSWAP[2] = self.DT + self.avrSWAP[60] = self.num_blade + + # --- warm-start initial states (replaces hard-coded values) --- + self.avrSWAP[19] = self.init_gen_speed # gen speed [rad/s] + self.avrSWAP[20] = self.init_rot_speed # rot speed [rad/s] + self.avrSWAP[82] = self.init_nac_imu # nac IMU + self.avrSWAP[26] = self.init_ws # wind speed [m/s] + self.avrSWAP[22] = self.init_torque # gen torque [Nm] + + # Initial blade pitch (all blades) + # passing in deg to swap to rad with standard ControllerInterface behavior + pitch_rad = np.deg2rad(self.pitch) + self.avrSWAP[3] = pitch_rad + self.avrSWAP[32] = pitch_rad + self.avrSWAP[33] = pitch_rad + + self.avrSWAP[27] = 1 # IPC flag + + # First-call init + self.avrSWAP[0] = 0 + + self.aviFAIL = c_int32() + self.accINFILE = self.param_name.encode("utf-8") + self.avcOUTNAME = self.sim_name.encode("utf-8") + self.avcMSG = create_string_buffer(1000) + + self.discon.DISCON.argtypes = [ + POINTER(c_float), + POINTER(c_int32), + c_char_p, + c_char_p, + c_char_p, + ] + + self.avrSWAP[48] = self.char_buffer + self.avrSWAP[49] = len(self.param_name) + self.avrSWAP[50] = len(self.avcOUTNAME) + self.avrSWAP[51] = self.char_buffer + + with suppress_fortran_output(): + self.call_discon() # iStatus=0 init call + + self.avrSWAP[0] = 1 # subsequent calls are normal + + if self.aviFAIL.value < 0: + raise ValueError("ROSCO dynamic library has returned an error") + + def kill_discon(self): + """ + Silent DISCON shutdown (suppresses ROSCO shutdown print spam). + Removes ROSCO FORTRAN output clean up terminal so MITRotor interface + outputs are visible. + """ + try: + with suppress_fortran_output(): # context manager + super().kill_discon() + except Exception: + pass + + +@contextmanager +def suppress_fortran_output(): + """Suppress Fortran prints (stdout/stderr) in this process.""" + sys.stdout.flush() + sys.stderr.flush() + + devnull = os.open(os.devnull, os.O_WRONLY) + old_stdout = os.dup(1) + old_stderr = os.dup(2) + try: + os.dup2(devnull, 1) + os.dup2(devnull, 2) + yield + finally: + os.dup2(old_stdout, 1) + os.dup2(old_stderr, 2) + os.close(old_stdout) + os.close(old_stderr) + os.close(devnull) + +# ----------------------------- +# ROSCO Convergence helper structures +# ----------------------------- +@dataclass +class ConvergenceSettings: + """ + Tunable parameters for steady-state convergence detection. + + Attributes + ---------- + warmup_time : float + Time to ignore before evaluating convergence, in seconds. + window_time : float + Length of rolling analysis window, in seconds. + hold_time : float + Duration for which all criteria must remain satisfied, in seconds. + tol_rel_power_std : float + Threshold on relative power variability: std(P)/|mean(P)|. + tol_domega_dt : float + Threshold on max rotor acceleration magnitude, in rad/s^2. + tol_dpitch_dt : float + Threshold on max pitch-rate magnitude, in rad/s. + """ + warmup_time: float = 60.0 + window_time: float = 20.0 + hold_time: float = 5.0 + tol_rel_power_std: float = 1e-3 + tol_domega_dt: float = 1e-3 + tol_dpitch_dt: float = np.deg2rad(1e-3) + + +def init_convergence_tracker(dt: float, settings: ConvergenceSettings): + """ + Create and initialize rolling-window state for convergence checks. + + Parameters + ---------- + dt : float + Simulation timestep in seconds. + settings : ConvergenceSettings + Convergence timing and tolerance settings. + + Returns + ------- + dict + Tracker containing step counts, rolling histories, and stable counter. + Keys include: `warmup_steps`, `window_steps`, `hold_steps`, + `stable_count`, `p_hist`, `omega_hist`, `pitch_hist`. + """ + warmup_steps = int(np.ceil(settings.warmup_time / dt)) + window_steps = int(np.ceil(settings.window_time / dt)) + hold_steps = int(np.ceil(settings.hold_time / dt)) + + tracker = { + "warmup_steps": warmup_steps, + "window_steps": window_steps, + "hold_steps": hold_steps, + "stable_count": 0, + "p_hist": deque(maxlen=window_steps), # W + "omega_hist": deque(maxlen=window_steps), # rad/s + "pitch_hist": deque(maxlen=window_steps), # rad + } + return tracker + + +def update_convergence_tracker(tracker, gen_power, rot_speed, bld_pitch): + """ + Append latest simulation values to rolling convergence histories. + + Parameters + ---------- + tracker : dict + Tracker dictionary created by `init_convergence_tracker`. + gen_power : float + Generator electrical power, in W. + rot_speed : float + Rotor speed, in rad/s. + bld_pitch : float + Collective blade pitch, in rad. + """ + tracker["p_hist"].append(float(gen_power)) + tracker["omega_hist"].append(float(rot_speed)) + tracker["pitch_hist"].append(float(bld_pitch)) + + +def compute_window_metrics(tracker, dt): + """ + Compute window-based convergence metrics from rolling histories. + + Parameters + ---------- + tracker : dict + Convergence tracker containing `p_hist`, `omega_hist`, `pitch_hist`. + dt : float + Simulation timestep in seconds. + + Returns + ------- + dict + Dictionary with: + - `p_mean` : mean power over window [W] + - `rel_p_std` : relative power std, std(P)/max(|mean(P)|, 1) + - `max_domega_dt` : max |d(omega)/dt| over window [rad/s^2] + - `max_dpitch_dt` : max |d(pitch)/dt| over window [rad/s] + """ + p = np.asarray(tracker["p_hist"]) + om = np.asarray(tracker["omega_hist"]) + th = np.asarray(tracker["pitch_hist"]) + + p_mean = float(np.mean(p)) + rel_p_std = float(np.std(p) / max(abs(p_mean), 1.0)) + max_domega_dt = float(np.max(np.abs(np.diff(om))) / dt) + max_dpitch_dt = float(np.max(np.abs(np.diff(th))) / dt) + + return { + "p_mean": p_mean, + "rel_p_std": rel_p_std, + "max_domega_dt": max_domega_dt, + "max_dpitch_dt": max_dpitch_dt, + } + + +def check_convergence(n_iter, dt, tracker, settings: ConvergenceSettings): + """ + Evaluate steady-state convergence criteria. + + Criteria + -------- + After warmup and once the rolling window is full, convergence is considered + satisfied at a given step if: + 1) relative power std < `tol_rel_power_std` + 2) max rotor acceleration < `tol_domega_dt` + 3) max pitch rate < `tol_dpitch_dt` + + These conditions must hold for `hold_steps` consecutive evaluations. + + Parameters + ---------- + n_iter : int + Current simulation iteration index. + dt : float + Simulation timestep in seconds. + tracker : dict + Convergence tracker dictionary. + settings : ConvergenceSettings + Convergence timing and tolerance settings. + + Returns + ------- + tuple[bool, dict | None] + `(converged, metrics)` where: + - `converged` is True if hold condition is met. + - `metrics` is None until checks become active; otherwise window metrics + from `compute_window_metrics`. + """ + if n_iter < tracker["warmup_steps"]: + return False, None + if len(tracker["p_hist"]) < tracker["window_steps"]: + return False, None + + metrics = compute_window_metrics(tracker, dt) + ok_power = metrics["rel_p_std"] < settings.tol_rel_power_std + ok_omega = metrics["max_domega_dt"] < settings.tol_domega_dt + ok_pitch = metrics["max_dpitch_dt"] < settings.tol_dpitch_dt + + if ok_power and ok_omega and ok_pitch: + tracker["stable_count"] += 1 + else: + tracker["stable_count"] = 0 + + converged = tracker["stable_count"] >= tracker["hold_steps"] + return converged, metrics \ No newline at end of file diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 0910a36..be5d286 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -1,37 +1,31 @@ # Python modules import os -from collections import deque -from ctypes import cdll, POINTER, c_float, c_int32, c_char_p, create_string_buffer -from dataclasses import dataclass import numpy as np -from pathlib import Path -from scipy.interpolate import interp1d, RegularGridInterpolator +from scipy.interpolate import RegularGridInterpolator import warnings -import sys -from contextlib import contextmanager # Parallelization modules from types import SimpleNamespace -from joblib import Parallel, delayed -from tqdm.auto import tqdm -from tqdm_joblib import tqdm_joblib # ROSCO toolbox modules from rosco import discon_lib_path as lib_name from rosco.toolbox import controller as ROSCO_controller from rosco.toolbox import turbine as ROSCO_turbine -from rosco.toolbox import control_interface as ROSCO_ci -from rosco.toolbox import sim as ROSCO_sim from rosco.toolbox.utilities import write_rotor_performance, write_DISCON from rosco.toolbox.inputs.validation import load_rosco_yaml -import time +# MITRotor Imports +import MITRotor.FlorisInterface.InterfaceUtilities as iu # ----------------------------- # Create Ct/Cp surfaces # ----------------------------- def load_from_mitrotor( - turbine, bem, refine_cp_surface=False, - TurbineName = "IEA15MW", rotor_performance_filename = 'Cp_Ct_Cq.txt', - GenEff = 95.756, generator_inertia = 1836784, - yaw = 0.0 + turbine, bem, + refine_cp_surface=False, + TurbineName = "IEA15MW", + rotor_performance_filename = 'Cp_Ct_Cq.txt', + GenEff = 95.756, + generator_inertia = 1836784, + yaw = 0.0, + tilt = 0.0, ): ''' Loads rotor performance information by running MITRotor aerodynamic analysis. @@ -46,6 +40,9 @@ def load_from_mitrotor( TurbineName (string): string turbine name; default to "IEA15MW" GenEff (float): generator efficiency (0-100); defaults to IEA15MW value 95.756 generator_inertia (float): generator_inertia; defaults to IEA15MW value 1836784 [kg m^2] + yaw (float): yaw with which to make Cp/Ct surface [deg] + tilt (float): tilt with which to make Cp/Ct surface [deg] + rotor_performance_filename (string): file name (including path) for saved Cp/Ct/Cq surface Returns: turbine with new fields needed for ROSCO controller, including Ct, Cp, and Cq surfaces ''' @@ -53,16 +50,22 @@ def load_from_mitrotor( turbine.TurbineName = TurbineName turbine.rotor_performance_filename = rotor_performance_filename + # Save needed paramters that are read into MITRotor turbine definition through ReferenceTurbines files (tower_height, gearbox_efficiency, gearbox_ratio, air_density) = bem.rotor.rosco_values turbine.TowerHt = tower_height turbine.GBoxEff = gearbox_efficiency turbine.Ng = gearbox_ratio turbine.rho = air_density + # Save remaining two needed generator parameters --> user needs to pass in! turbine.GenEff = GenEff turbine.generator_inertia = generator_inertia + # yaw and tilt for turbine/controller default Cp/Ct surface turbine.yaw = yaw + turbine.tilt = tilt + + # Calcualte remining needed values turbine.rotor_radius = bem.rotor.R turbine.J = turbine.rotor_inertia + turbine.generator_inertia * turbine.Ng**2 turbine.rated_torque = turbine.rated_power/(turbine.GenEff/100*turbine.rated_rotor_speed*turbine.Ng) @@ -73,7 +76,6 @@ def load_from_mitrotor( pitch_initial_rad = np.deg2rad(pitch_initial) tsr_mesh, pitch_rad_mesh = np.meshgrid(TSR_initial, pitch_initial_rad) - tsr_flat = tsr_mesh.ravel() pitch_rad_flat = pitch_rad_mesh.ravel() @@ -84,7 +86,7 @@ def load_from_mitrotor( pitch_rad_flat, tsr_flat, yaw=np.ones_like(tsr_flat) * turbine.yaw, - tilt=np.ones_like(tsr_flat) * np.deg2rad(5.0), + tilt=np.ones_like(tsr_flat) * turbine.tilt, ) print('MITRotor aerodynamic analysis run successfully.') @@ -109,7 +111,8 @@ def load_from_mitrotor( turbine.Ct = ROSCO_turbine.RotorPerformance(turbine.Ct_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) turbine.Cq = ROSCO_turbine.RotorPerformance(turbine.Cq_table,turbine.pitch_initial_rad,turbine.TSR_initial, refine=refine_cp_surface) - if not turbine.TSR_operational: # TODO: make it clear that this is reccomeneded! + # if TSR_operational is not reccomended, find max Cp TSR from Cp surface + if not turbine.TSR_operational: turbine.TSR_operational = turbine.Cp.TSR_opt return turbine @@ -119,19 +122,38 @@ def load_from_mitrotor( # ----------------------------- def get_rosco_control_interps( rosco_yaml, bem, - TurbineName="IEA15MW", rotor_performance_filename='Cp_Ct_Cq.txt', SimName="Sim1", - GenEff=95.756, generator_inertia=1836784, + TurbineName="IEA15MW", + rotor_performance_filename='Cp_Ct_Cq.txt', + SimName="Sim1", + GenEff=95.756, + generator_inertia=1836784, regenerate=False, save_control_file=None, save_dir=".", dt=0.05, yaw_grid_deg=np.arange(0.0, 25.0, 1.0), # degrees - n_jobs=-1, # parallel workers across wind speeds + n_jobs=-1, # parallel workers across wind speeds ): """ Creates pitch and tsr 2D interpolators using ROSCO controller tuning. - Parallelized over wind speeds; yaws for each wind are solved sequentially - in one worker with warm-start chaining. + Parallelized over yaws; wind speeds for each yaw are solved sequentially in one worker with warm-start chaining. + + Args: + rosco_yaml (str): Path to ROSCO controller YAML configuration file. + bem (MITRotor.BEM): MITRotor BEM object used to generate rotor performance surfaces. + TurbineName (str): Turbine name. Defaults to "IEA15MW". + rotor_performance_filename (str): File name (including path) for saved Cp/Ct/Cq surface. Defaults to "Cp_Ct_Cq.txt". + SimName (str): Simulation name used in ROSCO configuration. Defaults to "Sim1". + GenEff (float): Generator efficiency (0-100%). Defaults to IEA15MW value of 95.756. + generator_inertia (float): Generator inertia [kg m^2]. Defaults to IEA15MW value of 1836784. + regenerate (bool): If True, regenerate the rotor performance file even if one exists. Defaults to False. + save_control_file (str): Optional file name for saving the generated ROSCO control file. Defaults to None. + save_dir (str): Directory in which to save generated files. Defaults to ".". + dt (float): Controller timestep [s]. Defaults to 0.05. + yaw_grid_deg (array-like): Yaw angles [deg] used when generating Cp/Ct/Cq performance surfaces. Defaults to np.arange(0.0, 25.0, 1.0). + n_jobs (int): Number of parallel workers used when generating rotor performance surfaces across wind speeds. Defaults to -1 (all available workers). + + Returns: pitch_rad_interp, tsr_interp, turbine.rated_rotor_speed """ # Load ROSCO inputs and make basic turbine @@ -141,8 +163,8 @@ def get_rosco_control_interps( # If control csv exists and do not want to regenerate, load old csv if not regenerate and save_control_file is not None: - pitch_interp, tsr_interp = load_control_interps_from_csv(save_control_file) - return pitch_interp, tsr_interp, turbine.rated_rotor_speed + pitch_rad_interp, tsr_interp = iu.load_control_interps_from_csv(save_control_file) + return pitch_rad_interp, tsr_interp, turbine.rated_rotor_speed # Load and check control parameters controller_params = inps['controller_params'] @@ -151,13 +173,19 @@ def get_rosco_control_interps( "We suggest using WE_Mode = 0 or WE_Mode = 2 within the control parameter file.", UserWarning, ) + if (controller_params["VS_ControlMode"] == 2): + warnings.warn( + "We suggest NOT using VS_ControlMode = 2 within the control parameter file. Mismatched TSR definitions between MITRotor and" \ + "ROSCO lead to biased optimization.", + UserWarning, + ) # Generate turbine Cp/Ct surfaces turbine = load_from_mitrotor( turbine, bem, TurbineName=TurbineName, rotor_performance_filename=rotor_performance_filename, generator_inertia=generator_inertia, GenEff=GenEff, - yaw=0.0, + yaw=0.0, # Cp/Ct surface generated with yaw = 0 ) # Save turbine Cp/Ct surface @@ -177,12 +205,11 @@ def get_rosco_control_interps( ) # Tuned initial setpoints - init_pitch_list = np.rad2deg(np.maximum(controller.pitch_op, controller.ps_min_bld_pitch)) + init_pitch_rad_list = np.maximum(controller.pitch_op, controller.ps_min_bld_pitch) init_tsr_list = controller.TSR_op # Create parameter tables v_grid = controller.v.copy() - # v_grid = np.flip(v_grid) yaw_grid_deg = np.sort(np.asarray(yaw_grid_deg, dtype=float)) yaw_grid_rad = np.deg2rad(yaw_grid_deg) @@ -200,59 +227,13 @@ def get_rosco_control_interps( GenEff=float(turbine.GenEff), ) - # Calculate total number of cases - n_wind = len(v_grid) - n_yaw = len(yaw_grid_rad) - total_cases = n_wind * n_yaw - - # Determine effective n_jobs - if n_jobs is None: - n_jobs_eff = 1 - elif n_jobs == -1: - n_jobs_eff = min(os.cpu_count() or 1, n_wind) - else: - n_jobs_eff = max(1, min(int(n_jobs), n_wind)) - - # Run parallel (fallback to serial on failure, e.g., pickling issue) - print( - f"Starting control LUT sweep: {n_yaw} yaw tasks " - f"({total_cases} wind-yaw cases), using {n_jobs_eff} worker process(es)." - ) - - def _run_serial(desc): - out = [] - for i, yaw_rad in enumerate(tqdm(yaw_grid_rad, total=n_wind, desc=desc, dynamic_ncols=True)): - out.append( - _run_one_wind_row( - i, v_grid, yaw_rad, init_pitch_list, init_tsr_list, - turbine_sim, bem, param_filename, dt, SimName - ) - ) - return out - - cols = None - if n_jobs_eff > 1: - bar = tqdm(total=n_yaw, desc="Control LUT sweep (wind cols)", dynamic_ncols=True) - try: - with tqdm_joblib(bar): - cols = Parallel(n_jobs=n_jobs_eff, backend="loky", verbose=0, batch_size=1)( - delayed(_run_one_wind_row)( - i, v_grid, yaw_rad, init_pitch_list, init_tsr_list, - turbine_sim, bem, param_filename, dt, SimName - ) - for i, yaw_rad in enumerate(yaw_grid_rad) - ) - except Exception as e: - warnings.warn( - f"Parallel execution failed ({type(e).__name__}: {e}). " - "Falling back to serial execution.", - RuntimeWarning, - ) - finally: - bar.close() - if cols is None: - desc = "Control LUT sweep (serial fallback)" if n_jobs_eff > 1 else "Control LUT sweep (serial)" - cols = _run_serial(desc) + # run simulations in parallel or serial depending on n_jobs + def yaw_row_func(i, yaw_rad): + return _run_one_yaw_row( + i, v_grid, yaw_rad, init_pitch_rad_list, init_tsr_list, + turbine_sim, bem, param_filename, dt, SimName + ) + cols = iu.run_yaw_row_sim(v_grid, yaw_grid_rad, yaw_row_func, n_jobs) # Collect setpoints for i, pitch_col, tsr_col, power_col in cols: @@ -261,24 +242,10 @@ def _run_serial(desc): power_tbl[:, i] = power_col # Optional CSV save - if save_control_file is not None: - save_control_file = Path(save_control_file) - save_control_file.parent.mkdir(parents=True, exist_ok=True) - - vv, yy = np.meshgrid(v_grid, yaw_grid_rad, indexing="ij") - data = np.column_stack([ - vv.ravel(), # wind_speed_mps - yy.ravel(), # yaw_rad - pitch_tbl.ravel(), # pitch_rad - tsr_tbl.ravel(), # tsr - power_tbl.ravel(), # generated power - ]) - - header = "wind_speed_mps,yaw_rad,pitch_rad,tsr,gen_power" - np.savetxt(save_control_file, data, delimiter=",", header=header, comments="") + iu.save_control_interps_to_csv(save_control_file, v_grid, yaw_grid_rad, pitch_tbl, tsr_tbl, power_tbl) # Make interpolators - pitch_interp = RegularGridInterpolator( + pitch_rad_interp = RegularGridInterpolator( (v_grid, yaw_grid_rad), pitch_tbl, method="linear", bounds_error=False, fill_value=None ) @@ -286,11 +253,10 @@ def _run_serial(desc): (v_grid, yaw_grid_rad), tsr_tbl, method="linear", bounds_error=False, fill_value=None ) + return pitch_rad_interp, tsr_interp, turbine.rated_rotor_speed - return pitch_interp, tsr_interp, turbine.rated_rotor_speed - -def _run_one_wind_row( - i, v_grid, yaw_rad, init_pitch_deg_list, init_tsr_list, +def _run_one_yaw_row( + i, v_grid, yaw_rad, init_pitch_rad_list, init_tsr_list, turbine_sim, bem, param_filename, dt, SimName ): """ @@ -303,19 +269,17 @@ def _run_one_wind_row( tsr_col = np.full(nv, np.nan, dtype=float) power_col = np.full(nv, np.nan, dtype=float) - # Warm-start seeds for first yaw in this wind row - # prev_pitch_deg = float(init_pitch_deg0) - # prev_tsr = float(init_tsr0) - for j, v in enumerate(v_grid): + print(v, yaw_rad) controller_int = None try: - init_pitch_deg = init_pitch_deg_list[j] + init_pitch_rad = init_pitch_rad_list[j] + init_pitch_deg = np.rad2deg(init_pitch_rad) init_tsr = init_tsr_list[j] init_omega = init_tsr * v / turbine_sim.rotor_radius init_gen = init_omega * turbine_sim.Ng - controller_int = WarmStartControllerInterface( + controller_int = iu.WarmStartControllerInterface( lib_name, param_filename=param_filename, sim_name=f"{SimName}_{i}_{j}", @@ -334,9 +298,9 @@ def _run_one_wind_row( converged = sim_ws_mitrotor( sim=sim, bem=bem, ws=v, dt=dt, init_tsr=init_tsr, - init_pitch=init_pitch_deg, # deg - yaw_init=yaw_rad, # rad - wd=0.0, + init_pitch_rad=init_pitch_rad, # rad + init_yaw_rad=yaw_rad, # rad + wd=0.0, # rad verbose=False, ) @@ -348,7 +312,6 @@ def _run_one_wind_row( except Exception: # leave NaN and continue to next yaw - print("HELLO") if controller_int is not None: try: controller_int.kill_discon() @@ -359,97 +322,12 @@ def _run_one_wind_row( return i, pitch_col, tsr_col, power_col -def load_control_interps_from_csv(csv_path): - """ - Load wind/yaw control LUT CSV and return 2D interpolators. - - Expected CSV columns: - wind_speed_mps, yaw_rad, pitch_rad, tsr, gen_power - """ - data = np.genfromtxt(csv_path, delimiter=",", names=True) - - ws = np.asarray(data["wind_speed_mps"], dtype=float) - yaw = np.asarray(data["yaw_rad"], dtype=float) - pitch = np.asarray(data["pitch_rad"], dtype=float) - tsr = np.asarray(data["tsr"], dtype=float) - - v_grid = np.unique(ws) - yaw_grid = np.unique(yaw) - - # sort cols by (ws, yaw), then reshape into [n_ws, n_yaw] - order = np.lexsort((yaw, ws)) - n_ws, n_yaw = len(v_grid), len(yaw_grid) - - pitch_tbl = pitch[order].reshape(n_ws, n_yaw) - tsr_tbl = tsr[order].reshape(n_ws, n_yaw) - - pitch_interp = RegularGridInterpolator( - (v_grid, yaw_grid), pitch_tbl, - method="linear", bounds_error=False, fill_value=None - ) - tsr_interp = RegularGridInterpolator( - (v_grid, yaw_grid), tsr_tbl, - method="linear", bounds_error=False, fill_value=None - ) - - return pitch_interp, tsr_interp - - -def query_controls( - interp, - ws, - yaw_rad, - *, - kind="generic", # "pitch" or "tsr" - rated_rotor_speed=None, # rad/s (for 1D tsr scheme) - rotor_radius=None, # m (required if rated_rotor_speed is set) -): - """ - Supports: - - 2D RegularGridInterpolator: interp(ws, yaw) - - 1D interp1d/callable: interp(ws), yaw ignored (warn if |yaw| > 0) - - For 1D TSR and rated_rotor_speed provided: - applies simple above-rated cap via omega = tsr*ws/R. - """ - ws_arr = np.asarray(ws, dtype=float) - yaw_arr = np.asarray(yaw_rad, dtype=float) - ws_b, yaw_b = np.broadcast_arrays(ws_arr, yaw_arr) - - # 2D LUT path - if isinstance(interp, RegularGridInterpolator) and len(interp.grid) == 2: - pts = np.column_stack((ws_b.ravel(), yaw_b.ravel())) - vals = np.asarray(interp(pts)).reshape(ws_b.shape) - return float(vals) if vals.shape == () else vals - - # 1D legacy path - if np.any(np.abs(yaw_b) > 0): - warnings.warn( - "Using 1D control curve with nonzero yaw/tilt; yaw/tilt is ignored for lookup.", - UserWarning, - ) - - vals = np.asarray(interp(ws_b)).reshape(ws_b.shape) - - if kind == "tsr": - if rated_rotor_speed is not None: - if rotor_radius is None: - raise ValueError("rotor_radius is required when rated_rotor_speed is set.") - omega_lookup = vals * ws_b / np.maximum(rotor_radius, 1e-12) - tsr_from_rated = rated_rotor_speed * rotor_radius / np.maximum(ws_b, 1e-6) - vals = np.where(omega_lookup <= rated_rotor_speed, vals, tsr_from_rated) - - vals = np.maximum(vals, 0.0) - - return float(vals) if vals.shape == () else vals - - # ----------------------------- # Steady-state simulation # ----------------------------- def sim_ws_mitrotor( - sim, bem, ws, dt, init_tsr, init_pitch, - wd=0.0, yaw_init=0.0, + sim, bem, ws, dt, init_tsr, init_pitch_rad, + wd=0.0, init_yaw_rad=0.0, max_iter=20000, conv_settings=None, verbose=True, @@ -457,9 +335,19 @@ def sim_ws_mitrotor( """ Steady-state single-wind-speed simulation (no time history storage), with rolling-window convergence checks. + + ws: wind speed, (m/s) + init_tsr: tip speed ratio, (-) + init_pitch: initial blade pitch angle, (rad) + wd: wind direction, (rad) + yaw_init: initial "north" (or constant) yaw angle, (rad) + max_iter: maximum number of iterations to try for convergence (int), + conv_settings: settings that define convergence to steady state, (ConvergenceSettings) + verbose: print extra information if True, (bool) + """ if conv_settings is None: - conv_settings = ConvergenceSettings() + conv_settings = iu.ConvergenceSettings() # Turbine constants R = sim.turbine.rotor_radius @@ -470,16 +358,16 @@ def sim_ws_mitrotor( gen_eff = sim.turbine.GenEff / 100.0 # States - bld_pitch = np.deg2rad(init_pitch) # rad (init_pitch is deg) + bld_pitch = init_pitch_rad # rad rot_speed = (init_tsr * ws / R) # rad/s gen_speed = rot_speed * Ng # rad/s gen_torque = 0.0 # Nm gen_power = 0.0 # W - nac_yaw = yaw_init # deg - nac_yawrate = 0.0 # deg/s + nac_yaw = init_yaw_rad # rad + nac_yawrate = 0.0 # rad/s # Convergence tracker - tracker = init_convergence_tracker(dt, conv_settings) + tracker = iu.init_convergence_tracker(dt, conv_settings) n_iter = 0 t = 0.0 @@ -494,14 +382,11 @@ def sim_ws_mitrotor( yaw_err = wd - nac_yaw # BEM call - start = time.time() sol = bem( bld_pitch, tsr, yaw = yaw_err, - tilt = 0.0 # TODO: add in tilt + tilt = 0.0 # yaw here is "effective yaw" or total y-z plane offset ) - end = time.time() - t += (end - start) cp = float(np.ravel(sol.Cp())[0]) # Rotor dynamics calculations (same as used in ROSCO's sim_ws_series function) @@ -515,13 +400,13 @@ def sim_ws_mitrotor( "t": t, "dt": dt, "ws": ws, - "bld_pitch": bld_pitch, + "bld_pitch": bld_pitch, # rad "gen_torque": gen_torque, "gen_speed": gen_speed, "gen_eff": gen_eff, "rot_speed": rot_speed, - "Yaw_fromNorth": nac_yaw, - "Y_MeasErr": yaw_err, + "Yaw_fromNorth": nac_yaw, # rad + "Y_MeasErr": yaw_err, # rad } # Controller call; torque, blade pitch, and yaw rate outputs @@ -534,8 +419,8 @@ def sim_ws_mitrotor( nac_yaw += nac_yawrate * dt # Convergence tracking - update_convergence_tracker(tracker, gen_power, rot_speed, bld_pitch) - converged, metrics = check_convergence(n_iter, dt, tracker, conv_settings) + iu.update_convergence_tracker(tracker, gen_power, rot_speed, bld_pitch) + converged, metrics = iu.check_convergence(n_iter, dt, tracker, conv_settings) if metrics is not None: last_metrics = metrics @@ -571,353 +456,4 @@ def sim_ws_mitrotor( sim.n_iter = n_iter sim.converged = converged - print(ws, yaw_init, sim.bld_pitch, sim.tsr, t / n_iter) - - return converged - -# ----------------------------- -# Controller Interface -> child of ROSCOS's ControllerInterface -# ----------------------------- -class WarmStartControllerInterface(ROSCO_ci.ControllerInterface): - """ - ROSCO controller interface with configurable warm-start initial conditions. - - This subclass overrides the default `ControllerInterface` initialization so - the first DISCON call (`iStatus=0`) is seeded with user-provided initial - wind speed, rotor/generator speeds, pitch, torque, and nacelle IMU angle, - instead of hard-coded defaults. - - Notes - ----- - - This is useful for steady-state sweeps, where reducing startup transients - improves convergence speed and robustness. - - Units are expected to match ROSCO avrSWAP channel conventions. - """ - - def __init__( - self, - lib_name, - param_filename="DISCON.IN", - init_ws=10.0, # m/s - init_rot_speed=1.0, # rad/s - init_gen_speed=1.0, # rad/s - init_pitch_deg=0.0, # deg - init_torque=0.0, # Nm - init_nac_imu=0.0, # rad - **kwargs - ): - """ - Initialize warm-start settings and construct the ROSCO controller interface. - - Parameters - ---------- - lib_name : str - Path to the ROSCO dynamic library (.dll/.so/.dylib). - param_filename : str, optional - Path to DISCON input file, by default "DISCON.IN". - init_ws : float, optional - Initial wind speed used during DISCON init, in m/s. - init_rot_speed : float, optional - Initial low-speed shaft rotor speed, in rad/s. - init_gen_speed : float, optional - Initial generator speed (high-speed shaft), in rad/s. - init_pitch_deg : float, optional - Initial collective blade pitch, in degrees. - init_torque : float, optional - Initial generator torque, in Nm. - init_nac_imu : float, optional - Initial nacelle IMU angle/state, in radians. - **kwargs - Additional keyword arguments forwarded to - `ROSCO_ci.ControllerInterface` (e.g., `DT`, `sim_name`, etc.). - """ - # Set starting conditions - self.init_ws = float(init_ws) - self.init_rot_speed = float(init_rot_speed) - self.init_gen_speed = float(init_gen_speed) - self.init_torque = float(init_torque) - self.init_nac_imu = float(init_nac_imu) - - # Parent uses self.pitch for initial blade pitch - super().__init__( - lib_name, - param_filename=param_filename, - pitch=init_pitch_deg, - **kwargs - ) - - def init_discon(self): - """ - Initialize DISCON with warm-start avrSWAP values. - - This method allocates and populates the avrSWAP array, sets the first-call - status (`iStatus=0`), invokes DISCON once to initialize internal ROSCO states, - then switches to normal run mode (`iStatus=1`) for subsequent calls. - - Raises - ------ - ValueError - If ROSCO returns a negative `aviFAIL` error code during initialization. - """ - self.torque = self.init_torque - - # Load library + allocate swap - self.discon = cdll.LoadLibrary(self.lib_name) - self.avrSWAP = np.zeros(self.avr_size) - - # Required channels - self.avrSWAP[2] = self.DT - self.avrSWAP[60] = self.num_blade - - # --- warm-start initial states (replaces hard-coded values) --- - self.avrSWAP[19] = self.init_gen_speed # gen speed [rad/s] - self.avrSWAP[20] = self.init_rot_speed # rot speed [rad/s] - self.avrSWAP[82] = self.init_nac_imu # nac IMU - self.avrSWAP[26] = self.init_ws # wind speed [m/s] - self.avrSWAP[22] = self.init_torque # gen torque [Nm] - - # Initial blade pitch (all blades) - pitch_rad = np.deg2rad(self.pitch) - self.avrSWAP[3] = pitch_rad - self.avrSWAP[32] = pitch_rad - self.avrSWAP[33] = pitch_rad - - self.avrSWAP[27] = 1 # IPC flag - - # First-call init - self.avrSWAP[0] = 0 - - self.aviFAIL = c_int32() - self.accINFILE = self.param_name.encode("utf-8") - self.avcOUTNAME = self.sim_name.encode("utf-8") - self.avcMSG = create_string_buffer(1000) - - self.discon.DISCON.argtypes = [ - POINTER(c_float), - POINTER(c_int32), - c_char_p, - c_char_p, - c_char_p, - ] - - self.avrSWAP[48] = self.char_buffer - self.avrSWAP[49] = len(self.param_name) - self.avrSWAP[50] = len(self.avcOUTNAME) - self.avrSWAP[51] = self.char_buffer - - with suppress_fortran_output(): - self.call_discon() # iStatus=0 init call - - self.avrSWAP[0] = 1 # subsequent calls are normal - - if self.aviFAIL.value < 0: - raise ValueError("ROSCO dynamic library has returned an error") - - def kill_discon(self): - """ - Silent DISCON shutdown (suppresses ROSCO shutdown print spam). - Removes ROSCO FORTRAN output clean up terminal so MITRotor interface - outputs are visible. - """ - try: - with suppress_fortran_output(): # context manager - super().kill_discon() - except Exception: - pass - - -@contextmanager -def suppress_fortran_output(): - """Suppress Fortran prints (stdout/stderr) in this process.""" - sys.stdout.flush() - sys.stderr.flush() - - devnull = os.open(os.devnull, os.O_WRONLY) - old_stdout = os.dup(1) - old_stderr = os.dup(2) - try: - os.dup2(devnull, 1) - os.dup2(devnull, 2) - yield - finally: - os.dup2(old_stdout, 1) - os.dup2(old_stderr, 2) - os.close(old_stdout) - os.close(old_stderr) - os.close(devnull) - - -# ----------------------------- -# Convergence helper structures -# ----------------------------- -@dataclass -class ConvergenceSettings: - """ - Tunable parameters for steady-state convergence detection. - - Attributes - ---------- - warmup_time : float - Time to ignore before evaluating convergence, in seconds. - window_time : float - Length of rolling analysis window, in seconds. - hold_time : float - Duration for which all criteria must remain satisfied, in seconds. - tol_rel_power_std : float - Threshold on relative power variability: std(P)/|mean(P)|. - tol_domega_dt : float - Threshold on max rotor acceleration magnitude, in rad/s^2. - tol_dpitch_dt : float - Threshold on max pitch-rate magnitude, in rad/s. - """ - warmup_time: float = 60.0 - window_time: float = 20.0 - hold_time: float = 5.0 - tol_rel_power_std: float = 1e-3 - tol_domega_dt: float = 1e-3 - tol_dpitch_dt: float = np.deg2rad(1e-3) - - -def init_convergence_tracker(dt: float, settings: ConvergenceSettings): - """ - Create and initialize rolling-window state for convergence checks. - - Parameters - ---------- - dt : float - Simulation timestep in seconds. - settings : ConvergenceSettings - Convergence timing and tolerance settings. - - Returns - ------- - dict - Tracker containing step counts, rolling histories, and stable counter. - Keys include: `warmup_steps`, `window_steps`, `hold_steps`, - `stable_count`, `p_hist`, `omega_hist`, `pitch_hist`. - """ - warmup_steps = int(np.ceil(settings.warmup_time / dt)) - window_steps = int(np.ceil(settings.window_time / dt)) - hold_steps = int(np.ceil(settings.hold_time / dt)) - - tracker = { - "warmup_steps": warmup_steps, - "window_steps": window_steps, - "hold_steps": hold_steps, - "stable_count": 0, - "p_hist": deque(maxlen=window_steps), # W - "omega_hist": deque(maxlen=window_steps), # rad/s - "pitch_hist": deque(maxlen=window_steps), # rad - } - return tracker - - -def update_convergence_tracker(tracker, gen_power, rot_speed, bld_pitch): - """ - Append latest simulation values to rolling convergence histories. - - Parameters - ---------- - tracker : dict - Tracker dictionary created by `init_convergence_tracker`. - gen_power : float - Generator electrical power, in W. - rot_speed : float - Rotor speed, in rad/s. - bld_pitch : float - Collective blade pitch, in rad. - """ - tracker["p_hist"].append(float(gen_power)) - tracker["omega_hist"].append(float(rot_speed)) - tracker["pitch_hist"].append(float(bld_pitch)) - - -def compute_window_metrics(tracker, dt): - """ - Compute window-based convergence metrics from rolling histories. - - Parameters - ---------- - tracker : dict - Convergence tracker containing `p_hist`, `omega_hist`, `pitch_hist`. - dt : float - Simulation timestep in seconds. - - Returns - ------- - dict - Dictionary with: - - `p_mean` : mean power over window [W] - - `rel_p_std` : relative power std, std(P)/max(|mean(P)|, 1) - - `max_domega_dt` : max |d(omega)/dt| over window [rad/s^2] - - `max_dpitch_dt` : max |d(pitch)/dt| over window [rad/s] - """ - p = np.asarray(tracker["p_hist"]) - om = np.asarray(tracker["omega_hist"]) - th = np.asarray(tracker["pitch_hist"]) - - p_mean = float(np.mean(p)) - rel_p_std = float(np.std(p) / max(abs(p_mean), 1.0)) - max_domega_dt = float(np.max(np.abs(np.diff(om))) / dt) - max_dpitch_dt = float(np.max(np.abs(np.diff(th))) / dt) - - return { - "p_mean": p_mean, - "rel_p_std": rel_p_std, - "max_domega_dt": max_domega_dt, - "max_dpitch_dt": max_dpitch_dt, - } - - -def check_convergence(n_iter, dt, tracker, settings: ConvergenceSettings): - """ - Evaluate steady-state convergence criteria. - - Criteria - -------- - After warmup and once the rolling window is full, convergence is considered - satisfied at a given step if: - 1) relative power std < `tol_rel_power_std` - 2) max rotor acceleration < `tol_domega_dt` - 3) max pitch rate < `tol_dpitch_dt` - - These conditions must hold for `hold_steps` consecutive evaluations. - - Parameters - ---------- - n_iter : int - Current simulation iteration index. - dt : float - Simulation timestep in seconds. - tracker : dict - Convergence tracker dictionary. - settings : ConvergenceSettings - Convergence timing and tolerance settings. - - Returns - ------- - tuple[bool, dict | None] - `(converged, metrics)` where: - - `converged` is True if hold condition is met. - - `metrics` is None until checks become active; otherwise window metrics - from `compute_window_metrics`. - """ - # not ready yet - if n_iter < tracker["warmup_steps"]: - return False, None - if len(tracker["p_hist"]) < tracker["window_steps"]: - return False, None - - metrics = compute_window_metrics(tracker, dt) - - ok_power = metrics["rel_p_std"] < settings.tol_rel_power_std - ok_omega = metrics["max_domega_dt"] < settings.tol_domega_dt - ok_pitch = metrics["max_dpitch_dt"] < settings.tol_dpitch_dt - - if ok_power and ok_omega and ok_pitch: - tracker["stable_count"] += 1 - else: - tracker["stable_count"] = 0 - - converged = tracker["stable_count"] >= tracker["hold_steps"] - return converged, metrics \ No newline at end of file + return converged \ No newline at end of file diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 20158a9..247b69b 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -22,7 +22,8 @@ from MITRotor.Momentum import UnifiedMomentumLUT from MITRotor import BEM, BEMGeometry, IEA15MW from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp -from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls +from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps +from MITRotor.FlorisInterface.InterfaceUtilities import query_controls # THIS RUN HAD: diff --git a/examples/example_08_floris_rosco2.py b/examples/example_08_floris_rosco2.py index bbe3edb..73f8fc2 100644 --- a/examples/example_08_floris_rosco2.py +++ b/examples/example_08_floris_rosco2.py @@ -22,7 +22,8 @@ from MITRotor.Momentum import UnifiedMomentumLUT from MITRotor import BEM, BEMGeometry, IEA15MW from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp -from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps, query_controls +from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps +from MITRotor.FlorisInterface.InterfaceUtilities import query_controls figdir = Path("fig") @@ -42,6 +43,7 @@ def change_control_param(param_key, param_value, template_yaml, bem, regenerate pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( temp_yaml, bem, regenerate = regenerate, save_control_file = save_control_file, + n_jobs=1 ) return pitch_interp, tsr_interp, rated_rotor_speed diff --git a/poetry.lock b/poetry.lock index 34beb70..f12c5b7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "anyio" @@ -1549,7 +1549,7 @@ fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} -jsonschema-specifications = ">=2023.3.6" +jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} From c837f78613fed5791ac069a8dd819c7f1f2875fc Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 31 Jul 2026 13:04:00 -0400 Subject: [PATCH 40/50] Final cleaned up version --- MITRotor/FlorisInterface/FlorisInterface.py | 1 + MITRotor/FlorisInterface/ROSCOInterface.py | 65 ++-- analyze_crash_log.py | 120 -------- examples/example_08_floris_rosco.py | 117 ++++---- examples/example_08_floris_rosco2.py | 309 -------------------- 5 files changed, 84 insertions(+), 528 deletions(-) delete mode 100644 analyze_crash_log.py delete mode 100644 examples/example_08_floris_rosco2.py diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index f08392d..6c46d1e 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -100,6 +100,7 @@ def __attrs_post_init__(self): self.pitch_interp = default_pitch_interp() # 1D legacy default if self.tsr_interp is None: self.tsr_interp = default_tsr_interp() # 1D legacy default + super().__attrs_post_init__() def _get_state_key(self, velocities: np.ndarray, yaw_angles: np.ndarray, tilt_angles: np.ndarray) -> tuple: # saves key to uniquely identify farm state -> avoids re-solving for calls to power, thrust, and induction for same state diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index be5d286..7f479a1 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -264,41 +264,42 @@ def _run_one_yaw_row( Uses sequential warm-start across yaw in this row. Returns row arrays (pitch/tsr/power), with NaN on fail/non-convergence. """ + print(f"Starting ROSCO simulation for yaw = {yaw_rad}") nv = len(v_grid) pitch_col = np.full(nv, np.nan, dtype=float) tsr_col = np.full(nv, np.nan, dtype=float) - power_col = np.full(nv, np.nan, dtype=float) + power_col = np.full(nv, np.nan, dtype=float)\ + + j = 0 + init_pitch_rad = init_pitch_rad_list[j] + init_pitch_deg = np.rad2deg(init_pitch_rad) + init_tsr = init_tsr_list[j] + init_rot_speed = init_tsr * v_grid[j] / turbine_sim.rotor_radius + init_gen_speed = init_rot_speed * turbine_sim.Ng + + controller_int = iu.WarmStartControllerInterface( + lib_name, + param_filename=param_filename, + sim_name=f"{SimName}_{i}_{j}", + DT=dt, + init_ws=v_grid[j], + init_rot_speed=init_rot_speed, + init_gen_speed=init_gen_speed, + init_pitch_deg=init_pitch_deg, # deg + init_torque=0.0, + init_nac_imu=yaw_rad, # rad + ) + + # lightweight sim object compatible with sim_ws_mitrotor + sim = SimpleNamespace(turbine=turbine_sim, controller_int=controller_int) for j, v in enumerate(v_grid): - print(v, yaw_rad) controller_int = None try: - init_pitch_rad = init_pitch_rad_list[j] - init_pitch_deg = np.rad2deg(init_pitch_rad) - init_tsr = init_tsr_list[j] - init_omega = init_tsr * v / turbine_sim.rotor_radius - init_gen = init_omega * turbine_sim.Ng - - controller_int = iu.WarmStartControllerInterface( - lib_name, - param_filename=param_filename, - sim_name=f"{SimName}_{i}_{j}", - DT=dt, - init_ws=v, - init_rot_speed=init_omega, - init_gen_speed=init_gen, - init_pitch_deg=init_pitch_deg, # deg - init_torque=0.0, - init_nac_imu=yaw_rad, # rad - ) - - # lightweight sim object compatible with sim_ws_mitrotor - sim = SimpleNamespace(turbine=turbine_sim, controller_int=controller_int) - converged = sim_ws_mitrotor( sim=sim, bem=bem, ws=v, dt=dt, - init_tsr=init_tsr, - init_pitch_rad=init_pitch_rad, # rad + init_tsr=init_tsr_list[j], + init_pitch_rad=init_pitch_rad_list[j], # rad init_yaw_rad=yaw_rad, # rad wd=0.0, # rad verbose=False, @@ -311,14 +312,11 @@ def _run_one_yaw_row( power_col[j] = sim.gen_power except Exception: - # leave NaN and continue to next yaw - if controller_int is not None: - try: - controller_int.kill_discon() - except Exception: - pass continue + # Kill controller + sim.controller_int.kill_discon() + return i, pitch_col, tsr_col, power_col @@ -442,9 +440,6 @@ def sim_ws_mitrotor( if not converged and verbose: print(f"WARNING: hit max_iter={max_iter} without convergence") - # Kill controller - sim.controller_int.kill_discon() - # Save outputs sim.bld_pitch = bld_pitch # rad sim.tsr = rot_speed * R / max(ws, 1e-6) # TSR w.r.t. freestream diff --git a/analyze_crash_log.py b/analyze_crash_log.py deleted file mode 100644 index bc2443c..0000000 --- a/analyze_crash_log.py +++ /dev/null @@ -1,120 +0,0 @@ -import re -import matplotlib.pyplot as plt -import numpy as np -import matplotlib as mpl -from matplotlib.lines import Line2D - -def get_vals(logfile): - - # Parse lines that contain exactly 5 numbers: - # wind_speed, yaw, blade_pitch, tsr, avg_runtime - rows = [] - num_re = r"[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?" - - with open(logfile, "r", encoding="utf-8", errors="ignore") as f: - for line in f: - nums = re.findall(num_re, line) - if len(nums) == 5: - rows.append(tuple(map(float, nums))) - - if not rows: - raise RuntimeError("No 5-number data lines found in crash.log") - - wind, yaw, pitch, tsr, runtime = zip(*rows) - - wind = np.array(wind, dtype=float) - yaw = np.array(yaw, dtype=float) - pitch = np.array(pitch, dtype=float) - tsr = np.array(tsr, dtype=float) - runtime = np.array(runtime, dtype=float) - - # ---- filter unrealistic pitch values ---- - # Set these for your units: - # degrees example: -5 to 45 - # radians example: -0.1 to 0.8 - PITCH_MIN, PITCH_MAX = -5.0, 45.0 - - m = ( - np.isfinite(pitch) & np.isfinite(tsr) & np.isfinite(runtime) & - (pitch >= PITCH_MIN) & (pitch <= PITCH_MAX) & (wind >= 3) - ) - wind = wind[m] - pitch = pitch[m] - yaw = yaw[m] - tsr = tsr[m] - runtime = runtime[m] - return wind, pitch, yaw, tsr, runtime - -logfile1 = "crash_ps_3_yaw.log" -wind1, pitch1, yaw1, tsr1, runtime1 = get_vals(logfile1) - -logfile2 = "crash_ps_0_yaw.log" -wind2, pitch2, yaw2, tsr2, runtime2 = get_vals(logfile2) - -# 1) time vs wind speed, colored by yaw -plt.figure(figsize=(6, 4)) -sc = plt.scatter(wind1, runtime1, c=yaw1, cmap="viridis", alpha = 0.7, s=35) -plt.xlabel("Wind speed") -plt.ylabel("Average runtime") -plt.colorbar(sc, label="Yaw") -plt.tight_layout() -plt.savefig("time_vs_windspeed_colored_by_yaw.png", dpi=200) -plt.close() - -# 2) time vs tsr, colored by wind speed -plt.figure(figsize=(6, 4)) -sc = plt.scatter(tsr1, runtime1, c=yaw1, cmap="plasma", alpha = 0.7, s=35) -plt.xlabel("TSR") -plt.ylabel("Average runtime") -plt.colorbar(sc, label="Yaw") -plt.tight_layout() -plt.savefig("time_vs_tsr_colored_by_yaw.png", dpi=200) -plt.close() - -# 3) time vs wind speed, colored by tsr -plt.figure(figsize=(6, 4)) -sc = plt.scatter(wind1, runtime1, c=tsr1, cmap="plasma", alpha = 0.7, s=35) -plt.xlabel("Windspeed") -plt.ylabel("Average runtime") -plt.colorbar(sc, label="TSR") -plt.tight_layout() -plt.savefig("time_vs_wind_colored_by_tsr.png", dpi=200) -plt.close() - -# 4) time vs tsr colored by pitch - -# shared color normalization across both datasets -pitch1_deg = np.rad2deg(pitch1) -pitch2_deg = np.rad2deg(pitch2) -vmin = min(np.min(pitch1_deg), np.min(pitch2_deg)) -vmax = max(np.max(pitch1_deg), np.max(pitch2_deg)) -norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax) -cmap = "viridis_r" - -fig, ax = plt.subplots(figsize=(6, 4)) - -sc1 = ax.scatter(tsr1, runtime1,c = pitch1_deg, cmap=cmap, norm=norm, - alpha=0.7, s=35, marker="o") -sc2 = ax.scatter(tsr2, runtime2, c = pitch2_deg, cmap=cmap, norm=norm, - alpha=0.7, s=35, marker="v") - -ax.set_xlabel("TSR") -ax.set_ylabel("Average BEM Runtime") - -# one shared colorbar -sm = mpl.cm.ScalarMappable(norm=norm, cmap=cmap) -sm.set_array([]) # compatibility -cbar = fig.colorbar(sm, ax=ax, label="Pitch (deg)") - -# shape legend (independent of colormap) -shape_handles = [ - Line2D([0], [0], marker='o', linestyle='None', color='k', - markerfacecolor='gray', label='PS_Mode = 3'), - Line2D([0], [0], marker='v', linestyle='None', color='k', - markerfacecolor='gray', label='PS_Mode = 0'), -] -ax.legend(handles=shape_handles, title="Marker shape", loc="best") - -fig.tight_layout() -fig.savefig("time_vs_tsr_colored_by_pitch.png", dpi=200) -plt.close(fig) \ No newline at end of file diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 247b69b..2a8b48d 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -13,24 +13,13 @@ # FLORIS modules from floris import FlorisModel, TimeSeries -# ROSCO toolbox modules -from rosco.toolbox import controller as ROSCO_controller -from rosco.toolbox import turbine as ROSCO_turbine -from rosco.toolbox.inputs.validation import load_rosco_yaml - # MITRotor modules from MITRotor.Momentum import UnifiedMomentumLUT from MITRotor import BEM, BEMGeometry, IEA15MW -from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp +from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps from MITRotor.FlorisInterface.InterfaceUtilities import query_controls - -# THIS RUN HAD: -# VS_ControlMode: 2 -# WE_Mode: 0 - - figdir = Path("fig") def change_control_param(param_key, param_value, template_yaml, bem, regenerate = False, save_control_file = "control.csv"): @@ -94,36 +83,36 @@ def main(): # Load IEA15MW ROSCO parameters to make controllers start = time.time() - rosco_yaml_PS_Mode_3 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" + rosco_yaml_VS_1 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" # takes ~25min with 8 workers - rosco_PS_Mode_3_pitch_interp, rosco_PS_Mode_3_tsr_interp, rosco_PS_Mode_3_rated_rotorspeed = get_rosco_control_interps( - rosco_yaml_PS_Mode_3, bem, - regenerate = False, save_control_file = "control_ps_3.csv") - # regenerate = True, save_control_file = "control_ps_3.csv") + rosco_VS_1_pitch_interp, rosco_VS_1_tsr_interp, rosco_VS_1_rated_rotorspeed = get_rosco_control_interps( + rosco_yaml_VS_1, bem, + # regenerate = False, save_control_file = "control_vs_1.csv") + regenerate = True, save_control_file = "control_vs_1.csv") end = time.time() print(f"Time to make control CSV: {end - start}") - - rosco_PS_Mode_0_pitch_interp, rosco_PS_Mode_0_tsr_interp, rosco_PS_Mode_0_rated_rotorspeed = change_control_param( - "PS_Mode", 0, rosco_yaml_PS_Mode_3, bem, - # regenerate = True, save_control_file = "control_ps_0.csv", - regenerate = False, save_control_file = "control_ps_0.csv" + # takes ~25min with 8 workers + rosco_VS_3_pitch_interp, rosco_VS_3_tsr_interp, rosco_VS_3_rated_rotorspeed = change_control_param( + "VS_ControlMode", 3, rosco_yaml_VS_1, bem, + regenerate = True, save_control_file = "control_vs_3.csv", + # regenerate = False, save_control_file = "control_vs_3.csv" ) - # Plot IEA15MW control from ROSCO paper, ROSOC control with PS_Mode = 3, and ROSOC control with PS_Mode = 0 + # Plot IEA15MW control from ROSCO paper, ROSOC control with VS_Control_Mode = 1, and ROSOC control withVS_Control_Mode = 3 pitch_abbas = abbas_pitch_interp(wind_speeds) - pitch_ps0 = np.rad2deg(query_controls(rosco_PS_Mode_0_pitch_interp, wind_speeds, 0.0)) - pitch_ps3 = np.rad2deg(query_controls(rosco_PS_Mode_3_pitch_interp, wind_speeds, 0.0)) + pitch_ps0 = np.rad2deg(query_controls(rosco_VS_3_pitch_interp, wind_speeds, 0.0)) + pitch_ps3 = np.rad2deg(query_controls(rosco_VS_1_pitch_interp, wind_speeds, 0.0)) tsr_abbas = abbas_tsr_interp(wind_speeds) - tsr_ps0 = query_controls(rosco_PS_Mode_0_tsr_interp, wind_speeds, 0.0) - tsr_ps3 = query_controls(rosco_PS_Mode_3_tsr_interp, wind_speeds, 0.0) + tsr_ps0 = query_controls(rosco_VS_3_tsr_interp, wind_speeds, 0.0) + tsr_ps3 = query_controls(rosco_VS_1_tsr_interp, wind_speeds, 0.0) # Create figure fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) fig.suptitle(fr"Setpoint Trajectories") # Plot pitch - ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO: PS_Mode = 0", lw=3) - ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") + ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO:VS_Control_Mode = 3", lw=3) + ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dashed") ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") ax[0].set_xlabel("Wind Speed [m/s]") @@ -132,8 +121,8 @@ def main(): ax[0].grid(True) # Plot TSR - ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO: PS_Mode = 0", lw=3) - ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: PS_Mode = 3", lw=3, linestyle = "dashed") + ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO:VS_Control_Mode = 3", lw=3) + ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dashed") ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") ax[1].set_xlabel("Wind Speed [m/s]") @@ -156,20 +145,20 @@ def main(): tsr_interp = abbas_tsr_interp, ) - floris_PS_Mode_0_turbine = MITRotorTurbine( + floris_VS_3_turbine = MITRotorTurbine( bem_model = bem, - pitch_interp = rosco_PS_Mode_0_pitch_interp, + pitch_interp = rosco_VS_3_pitch_interp, pitch_rad = True, - tsr_interp = rosco_PS_Mode_0_tsr_interp, - rated_rotor_speed = rosco_PS_Mode_0_rated_rotorspeed, + tsr_interp = rosco_VS_3_tsr_interp, + rated_rotor_speed = rosco_VS_3_rated_rotorspeed, ) - floris_PS_Mode_3_turbine = MITRotorTurbine( + floris_VS_1_turbine = MITRotorTurbine( bem_model = bem, - pitch_interp = rosco_PS_Mode_3_pitch_interp, + pitch_interp = rosco_VS_1_pitch_interp, pitch_rad = True, - tsr_interp = rosco_PS_Mode_3_tsr_interp, - rated_rotor_speed = rosco_PS_Mode_3_rated_rotorspeed, + tsr_interp = rosco_VS_1_tsr_interp, + rated_rotor_speed = rosco_VS_1_rated_rotorspeed, ) yaw = 0.0 # degrees yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] @@ -187,19 +176,19 @@ def main(): Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) - fmodel_PS_Mode_0 = FlorisModel("defaults") - fmodel_PS_Mode_0.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_PS_Mode_0.set_operation_model(floris_PS_Mode_0_turbine) - fmodel_PS_Mode_0.run() - Ct_PS_Mode_0 = fmodel_PS_Mode_0.get_turbine_thrust_coefficients() - Cp_PS_Mode_0, P_PS_Mode_0 = get_turbine_power_coefficent(floris_PS_Mode_0_turbine, fmodel_PS_Mode_0, wind_speeds) + fmodel_VS_3 = FlorisModel("defaults") + fmodel_VS_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_VS_3.set_operation_model(floris_VS_3_turbine) + fmodel_VS_3.run() + Ct_VS_3 = fmodel_VS_3.get_turbine_thrust_coefficients() + Cp_VS_3, P_VS_3 = get_turbine_power_coefficent(floris_VS_3_turbine, fmodel_VS_3, wind_speeds) - fmodel_PS_Mode_3 = FlorisModel("defaults") - fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) - fmodel_PS_Mode_3.run() - Ct_PS_Mode_3 = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() - Cp_PS_Mode_3, P_PS_Mode_3 = get_turbine_power_coefficent(floris_PS_Mode_3_turbine, fmodel_PS_Mode_3, wind_speeds) + fmodel_VS_1 = FlorisModel("defaults") + fmodel_VS_1.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_VS_1.set_operation_model(floris_VS_1_turbine) + fmodel_VS_1.run() + Ct_VS_1 = fmodel_VS_1.get_turbine_thrust_coefficients() + Cp_VS_1, P_VS_1 = get_turbine_power_coefficent(floris_VS_1_turbine, fmodel_VS_1, wind_speeds) # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (16,4), constrained_layout=True) @@ -213,10 +202,10 @@ def main(): lw=3, linestyle = "solid", zorder = 1, ) ax1.plot( - wind_speeds, Ct_PS_Mode_0, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 0", + wind_speeds, Ct_VS_3, label="FLORIS+MITROTOR+ROSCO:VS_Control_Mode = 3", lw=3, linestyle = "dashed", zorder = 1, ) - ax1.plot(wind_speeds, Ct_PS_Mode_3, label="FLORIS+MITROTOR+ROSCO: PS_Mode = 3", + ax1.plot(wind_speeds, Ct_VS_1, label="FLORIS+MITROTOR+ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dotted", zorder = 1, ) ax1.set_xlabel("Wind Speed [m/s]") @@ -233,10 +222,10 @@ def main(): lw=3, linestyle = "solid", zorder = 1, ) ax2.plot( - wind_speeds, Cp_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + wind_speeds, Cp_VS_3, label="FLORIS + MITROTOR + ROSCO:VS_Control_Mode = 3", lw=3, linestyle = "dashed", zorder = 1, ) - ax2.plot(wind_speeds, Cp_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", + ax2.plot(wind_speeds, Cp_VS_1, label="FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dotted", zorder = 1, ) ax2.set_xlabel("Wind Speed [m/s]") @@ -253,10 +242,10 @@ def main(): lw=3, linestyle = "solid", zorder = 1, ) ax3.plot( - wind_speeds, P_PS_Mode_0, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 0", + wind_speeds, P_VS_3, label="FLORIS + MITROTOR + ROSCO:VS_Control_Mode = 3", lw=3, linestyle = "dashed", zorder = 1, ) - ax3.plot(wind_speeds, P_PS_Mode_3, label="FLORIS + MITROTOR + ROSCO: PS_Mode = 3", + ax3.plot(wind_speeds, P_VS_1, label="FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dotted", zorder = 1, ) ax3.axhline(y = 15, lw=3, linestyle = "dotted", zorder = 0, color = "k", label = "15MW") @@ -271,15 +260,15 @@ def main(): # plot the difference in CT/CP curves for different yaw values yaw_list = [0.0, 10.0, 20.0] # degrees fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) - fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: PS_Mode = 3") + fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1") for (i, yaw) in enumerate(yaw_list): yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] - fmodel_PS_Mode_3 = FlorisModel("defaults") - fmodel_PS_Mode_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_PS_Mode_3.set_operation_model(floris_PS_Mode_3_turbine) - fmodel_PS_Mode_3.run() - ct = fmodel_PS_Mode_3.get_turbine_thrust_coefficients() - cp, p = get_turbine_power_coefficent(floris_PS_Mode_3_turbine, fmodel_PS_Mode_3, wind_speeds) + fmodel_VS_1 = FlorisModel("defaults") + fmodel_VS_1.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) + fmodel_VS_1.set_operation_model(floris_VS_1_turbine) + fmodel_VS_1.run() + ct = fmodel_VS_1.get_turbine_thrust_coefficients() + cp, p = get_turbine_power_coefficent(floris_VS_1_turbine, fmodel_VS_1, wind_speeds) ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", lw=3, linestyle = "solid", zorder = 1, diff --git a/examples/example_08_floris_rosco2.py b/examples/example_08_floris_rosco2.py deleted file mode 100644 index 73f8fc2..0000000 --- a/examples/example_08_floris_rosco2.py +++ /dev/null @@ -1,309 +0,0 @@ -# Python modules -import os -import matplotlib.pyplot as plt -import tempfile -from pathlib import Path -from ruamel.yaml import YAML -import numpy as np -import pandas as pd -import polars as pl -from scipy.interpolate import interp1d -import time - -# FLORIS modules -from floris import FlorisModel, TimeSeries - -# ROSCO toolbox modules -from rosco.toolbox import controller as ROSCO_controller -from rosco.toolbox import turbine as ROSCO_turbine -from rosco.toolbox.inputs.validation import load_rosco_yaml - -# MITRotor modules -from MITRotor.Momentum import UnifiedMomentumLUT -from MITRotor import BEM, BEMGeometry, IEA15MW -from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory, default_pitch_interp, default_tsr_interp -from MITRotor.FlorisInterface.ROSCOInterface import get_rosco_control_interps -from MITRotor.FlorisInterface.InterfaceUtilities import query_controls - -figdir = Path("fig") - -def change_control_param(param_key, param_value, template_yaml, bem, regenerate = False, save_control_file = "control.csv"): - yaml = YAML() - with tempfile.TemporaryDirectory() as tmpdir: - temp_yaml = Path(tmpdir) / "rosco_temp.yaml" - - with open(template_yaml) as f: - data = yaml.load(f) - - data["controller_params"][param_key] = param_value - - with open(temp_yaml, "w") as f: - yaml.dump(data, f) - - pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( - temp_yaml, bem, - regenerate = regenerate, save_control_file = save_control_file, - n_jobs=1 - ) - return pitch_interp, tsr_interp, rated_rotor_speed - -def get_turbine_power_coefficent(fturbine, fmodel, wind_speeds): - rotor_area = np.pi * fturbine.bem_model.rotor.R**2 - floris_power = np.squeeze(fmodel.get_turbine_powers()) - floris_Cp = floris_power / (0.5 * 1.225 * rotor_area * (wind_speeds)**3 * fturbine.eff_ratio) - return floris_Cp, floris_power / 1e6 # MW - -def main(): - # wind condtions - wind_speeds = np.linspace(3, 25, 25) - wind_dirs = np.full_like(wind_speeds, 270.0) - turbulence_intensity = np.zeros_like(wind_speeds) - time_series = TimeSeries( - wind_speeds=wind_speeds, - wind_directions=wind_dirs, - turbulence_intensities=turbulence_intensity, - ) - - # load example trajectories from ROSCO Paper Figure 2: - # Abbas, N. J., Zalkind, D. S., Pao, L., & Wright, A. (2022). - # A reference open-source controller for fixed and floating offshore wind turbines. - # Wind Energy Science, 7(1), 53-73. - abbas_pitch = pd.read_csv("examples/examples_in/IEA15_pitch.csv") # note that this is in degrees - abbas_tsr = pd.read_csv("examples/examples_in/IEA15_TSR.csv") - abbas_pitch_interp = interp1d(abbas_pitch["x"], abbas_pitch["y"], kind="linear", fill_value="extrapolate", bounds_error=False) - abbas_tsr_interp = interp1d(abbas_tsr["x"], abbas_tsr["y"], kind="linear", fill_value="extrapolate", bounds_error=False) - - # create new MITRotor BEM model with a LUT for UMM - print("Generating new LUT for BEM.") - cache_dir = Path("cache") - cache_dir.mkdir(exist_ok=True, parents=True) - cache_file = cache_dir / "lut.csv" - lut_model = UnifiedMomentumLUT( - cache_fn=cache_file, - regenerate=False, - LUT_Cts=np.linspace(-0.5,1.5,40), - LUT_yaws=np.linspace(0.0,40.0,40), - ) - print("LUT for BEM done generating. ") - bem = BEM(rotor = IEA15MW(), momentum_model = lut_model, geometry = BEMGeometry(Nr=10, Ntheta=20)) - - # Load IEA15MW ROSCO parameters to make controllers - start = time.time() - rosco_yaml_VS_1 = "MITRotor/ReferenceTurbines/ROSCO_IEA15MW.yaml" - # takes ~25min with 8 workers - rosco_VS_1_pitch_interp, rosco_VS_1_tsr_interp, rosco_VS_1_rated_rotorspeed = get_rosco_control_interps( - rosco_yaml_VS_1, bem, - regenerate = False, save_control_file = "control_vs_1.csv") - # regenerate = True, save_control_file = "control_vs_1.csv") - end = time.time() - print(f"Time to make control CSV: {end - start}") - - rosco_VS_3_pitch_interp, rosco_VS_3_tsr_interp, rosco_VS_3_rated_rotorspeed = change_control_param( - "VS_ControlMode", 3, rosco_yaml_VS_1, bem, - regenerate = True, save_control_file = "control_vs_3.csv", - # regenerate = False, save_control_file = "control_vs_3.csv" - ) - - # Plot IEA15MW control from ROSCO paper, ROSOC control with VS_Control_Mode = 1, and ROSOC control withVS_Control_Mode = 3 - pitch_abbas = abbas_pitch_interp(wind_speeds) - pitch_ps0 = np.rad2deg(query_controls(rosco_VS_3_pitch_interp, wind_speeds, 0.0)) - pitch_ps3 = np.rad2deg(query_controls(rosco_VS_1_pitch_interp, wind_speeds, 0.0)) - - tsr_abbas = abbas_tsr_interp(wind_speeds) - tsr_ps0 = query_controls(rosco_VS_3_tsr_interp, wind_speeds, 0.0) - tsr_ps3 = query_controls(rosco_VS_1_tsr_interp, wind_speeds, 0.0) - - # Create figure - fig, ax = plt.subplots(1, 2, figsize = (10,4), sharey = True, constrained_layout=True) - fig.suptitle(fr"Setpoint Trajectories") - # Plot pitch - ax[0].plot(wind_speeds, pitch_ps0, label="ROSCO:VS_Control_Mode = 3", lw=3) - ax[0].plot(wind_speeds, pitch_ps3, label="ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dashed") - ax[0].plot(wind_speeds, pitch_abbas, label="Abbas et al. Fig 2", lw=3, linestyle = "dotted") - - ax[0].set_xlabel("Wind Speed [m/s]") - ax[0].set_ylabel("Pitch [deg]") - ax[0].set_title("Pitch Schedule") - ax[0].grid(True) - - # Plot TSR - ax[1].plot(wind_speeds, tsr_ps0, label="MITRotor+FLORIS+ROSCO:VS_Control_Mode = 3", lw=3) - ax[1].plot(wind_speeds, tsr_ps3, label="MITRotor+FLORIS+ROSCO: VS_Control_Mode = 1", lw=3, linestyle = "dashed") - ax[1].plot(wind_speeds, tsr_abbas, label="Abbas et al. ROSCO Control", lw=3, linestyle = "dotted") - - ax[1].set_xlabel("Wind Speed [m/s]") - ax[1].set_ylabel("TSR [-]") - ax[1].set_title("Tip-Speed Ratio (TSR) Schedule") - ax[1].grid(True) - ax[1].legend() - - plt.savefig(figdir / "example_8_IEA15mw_controls.png", dpi=300) - - # make FLORIS turbines - floris_default_turbine = MITRotorTurbine( - bem_model = bem, - ) - - floris_abbas_turbine = MITRotorTurbine( - bem_model = bem, - pitch_interp = abbas_pitch_interp, - pitch_rad = False, - tsr_interp = abbas_tsr_interp, - ) - - floris_VS_3_turbine = MITRotorTurbine( - bem_model = bem, - pitch_interp = rosco_VS_3_pitch_interp, - pitch_rad = True, - tsr_interp = rosco_VS_3_tsr_interp, - rated_rotor_speed = rosco_VS_3_rated_rotorspeed, - ) - - floris_VS_1_turbine = MITRotorTurbine( - bem_model = bem, - pitch_interp = rosco_VS_1_pitch_interp, - pitch_rad = True, - tsr_interp = rosco_VS_1_tsr_interp, - rated_rotor_speed = rosco_VS_1_rated_rotorspeed, - ) - yaw = 0.0 # degrees - yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] - fmodel_default = FlorisModel("defaults") - fmodel_default.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_default.set_operation_model(floris_default_turbine) - fmodel_default.run() - Ct_default = fmodel_default.get_turbine_thrust_coefficients() - Cp_default, P_default = get_turbine_power_coefficent(floris_default_turbine, fmodel_default, wind_speeds) - - fmodel_abbas = FlorisModel("defaults") - fmodel_abbas.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_abbas.set_operation_model(floris_abbas_turbine) - fmodel_abbas.run() - Ct_abbas = fmodel_abbas.get_turbine_thrust_coefficients() - Cp_abbas, P_abbas = get_turbine_power_coefficent(floris_abbas_turbine, fmodel_abbas, wind_speeds) - - fmodel_VS_3 = FlorisModel("defaults") - fmodel_VS_3.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_VS_3.set_operation_model(floris_VS_3_turbine) - fmodel_VS_3.run() - Ct_VS_3 = fmodel_VS_3.get_turbine_thrust_coefficients() - Cp_VS_3, P_VS_3 = get_turbine_power_coefficent(floris_VS_3_turbine, fmodel_VS_3, wind_speeds) - - fmodel_VS_1 = FlorisModel("defaults") - fmodel_VS_1.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_VS_1.set_operation_model(floris_VS_1_turbine) - fmodel_VS_1.run() - Ct_VS_1 = fmodel_VS_1.get_turbine_thrust_coefficients() - Cp_VS_1, P_VS_1 = get_turbine_power_coefficent(floris_VS_1_turbine, fmodel_VS_1, wind_speeds) - - # plot CT values against one another and against IEA15MW from figure 3.1-C (https://docs.nlr.gov/docs/fy20osti/75698.pdf) - fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (16,4), constrained_layout=True) - fig.suptitle(fr"$C_T$ and $C_P$ with Yaw = {yaw} for Different Control Strategies") - ax1.plot( - wind_speeds, Ct_default, label="FLORIS+MITROTOR + Gaertner et al. Control", - lw=3, linestyle = "solid", zorder = 1, - ) - ax1.plot( - wind_speeds, Ct_abbas, label="FLORIS+MITROTOR Abbas et al. Control", - lw=3, linestyle = "solid", zorder = 1, - ) - ax1.plot( - wind_speeds, Ct_VS_3, label="FLORIS+MITROTOR+ROSCO:VS_Control_Mode = 3", - lw=3, linestyle = "dashed", zorder = 1, - ) - ax1.plot(wind_speeds, Ct_VS_1, label="FLORIS+MITROTOR+ROSCO: VS_Control_Mode = 1", - lw=3, linestyle = "dotted", zorder = 1, - ) - ax1.set_xlabel("Wind Speed [m/s]") - ax1.set_ylabel("$C_T [-]$") - ax1.set_title("$C_T$") - ax1.grid(True) - - ax2.plot( - wind_speeds, Cp_default, label="Gaertner et al. IEA15MW Ref", - lw=3, linestyle = "solid", zorder = 1, - ) - ax2.plot( - wind_speeds, Cp_abbas, label="Abbas et al. ROSCO Control", - lw=3, linestyle = "solid", zorder = 1, - ) - ax2.plot( - wind_speeds, Cp_VS_3, label="FLORIS + MITROTOR + ROSCO:VS_Control_Mode = 3", - lw=3, linestyle = "dashed", zorder = 1, - ) - ax2.plot(wind_speeds, Cp_VS_1, label="FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1", - lw=3, linestyle = "dotted", zorder = 1, - ) - ax2.set_xlabel("Wind Speed [m/s]") - ax2.set_ylabel("$C_P [-]$") - ax2.set_title("$C_P$") - ax2.grid(True) - - ax3.plot( - wind_speeds, P_default, label="Gaertner et al. IEA15MW Ref", - lw=3, linestyle = "solid", zorder = 1, - ) - ax3.plot( - wind_speeds, P_abbas, label="Abbas et al. ROSCO Control", - lw=3, linestyle = "solid", zorder = 1, - ) - ax3.plot( - wind_speeds, P_VS_3, label="FLORIS + MITROTOR + ROSCO:VS_Control_Mode = 3", - lw=3, linestyle = "dashed", zorder = 1, - ) - ax3.plot(wind_speeds, P_VS_1, label="FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1", - lw=3, linestyle = "dotted", zorder = 1, - ) - ax3.axhline(y = 15, lw=3, linestyle = "dotted", zorder = 0, color = "k", label = "15MW") - ax3.set_xlabel("Wind Speed [m/s]") - ax3.set_ylabel("$Power [MW]$") - ax3.set_title("$Power$") - ax3.grid(True) - ax3.legend(loc = 'lower right') - - plt.savefig(figdir / "example_8_IEA15mw_CT_CP.png", dpi=300) - - # plot the difference in CT/CP curves for different yaw values - yaw_list = [0.0, 10.0, 20.0] # degrees - fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3, sharey = False, figsize = (10,4), constrained_layout=True) - fig.suptitle(fr"$C_T$ and $C_P$ under Yaw for FLORIS + MITROTOR + ROSCO: VS_Control_Mode = 1") - for (i, yaw) in enumerate(yaw_list): - yaw_angles = [[yaw] for _ in np.arange(len(wind_speeds))] - fmodel_VS_1 = FlorisModel("defaults") - fmodel_VS_1.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series, yaw_angles = yaw_angles) - fmodel_VS_1.set_operation_model(floris_VS_1_turbine) - fmodel_VS_1.run() - ct = fmodel_VS_1.get_turbine_thrust_coefficients() - cp, p = get_turbine_power_coefficent(floris_VS_1_turbine, fmodel_VS_1, wind_speeds) - - ax1.plot(wind_speeds, ct, label=fr"Yaw = ${yaw}^\circ$", - lw=3, linestyle = "solid", zorder = 1, - ) - ax2.plot(wind_speeds, cp, label=fr"Yaw = ${yaw}^\circ$", - lw=3, linestyle = "solid", zorder = 1, - ) - ax3.plot(wind_speeds, p, label=fr"Yaw = ${yaw}^\circ$", - lw=3, linestyle = "solid", zorder = 1, - ) - - ax1.set_xlabel("Wind Speed [m/s]") - ax1.set_ylabel("$C_T [-]$") - ax1.set_title("$C_T$") - ax1.grid(True) - - ax2.set_xlabel("Wind Speed [m/s]") - ax2.set_ylabel("$C_P [-]$") - ax2.set_title("$C_P$") - ax2.grid(True) - - ax3.axhline(y = 15, lw=3, linestyle = "dotted", zorder = 0, color = "k", label = "15MW") - ax3.set_xlabel("Wind Speed [m/s]") - ax3.set_ylabel("$Power [MW]$") - ax3.set_title("$Power$") - ax3.grid(True) - ax3.legend() - plt.savefig(figdir / "example_8_IEA15mw_CT_CP_yawed.png", dpi=300) - - -if __name__ == "__main__": - main() \ No newline at end of file From 42efda1b84fe700c9093fa284c23f5397a08f801 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 31 Jul 2026 15:44:57 -0400 Subject: [PATCH 41/50] Finish updating floris rosco example --- examples/example_08_floris_rosco.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 2a8b48d..f3ebe3d 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -87,15 +87,15 @@ def main(): # takes ~25min with 8 workers rosco_VS_1_pitch_interp, rosco_VS_1_tsr_interp, rosco_VS_1_rated_rotorspeed = get_rosco_control_interps( rosco_yaml_VS_1, bem, - # regenerate = False, save_control_file = "control_vs_1.csv") - regenerate = True, save_control_file = "control_vs_1.csv") + regenerate = False, save_control_file = "control_vs_1.csv") + # regenerate = True, save_control_file = "control_vs_1.csv") end = time.time() print(f"Time to make control CSV: {end - start}") # takes ~25min with 8 workers rosco_VS_3_pitch_interp, rosco_VS_3_tsr_interp, rosco_VS_3_rated_rotorspeed = change_control_param( "VS_ControlMode", 3, rosco_yaml_VS_1, bem, - regenerate = True, save_control_file = "control_vs_3.csv", - # regenerate = False, save_control_file = "control_vs_3.csv" + # regenerate = True, save_control_file = "control_vs_3.csv", + regenerate = False, save_control_file = "control_vs_3.csv" ) # Plot IEA15MW control from ROSCO paper, ROSOC control with VS_Control_Mode = 1, and ROSOC control withVS_Control_Mode = 3 From da5bc4c79c91b8f8bfb2a9d8a76a3d31f86d41fd Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Mon, 3 Aug 2026 09:23:52 -0400 Subject: [PATCH 42/50] Added in docs --- MITRotor/Aerodynamics.py | 2 +- MITRotor/FlorisInterface/FlorisInterface.py | 38 +++- MITRotor/Momentum.py | 18 +- examples/MITRotor_quickstart.ipynb | 185 +++++++++++++++++--- examples/example_08_floris_rosco.py | 8 +- 5 files changed, 205 insertions(+), 46 deletions(-) diff --git a/MITRotor/Aerodynamics.py b/MITRotor/Aerodynamics.py index bd761a0..6a501e4 100644 --- a/MITRotor/Aerodynamics.py +++ b/MITRotor/Aerodynamics.py @@ -194,7 +194,7 @@ def __call__( AerodynamicProperties: Calculated aerodynamic properties stored in AerodynamicProperties object. """ - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the KraghAerodynamics model. Use DefaultAerodynamics.") local_yaw = wdir - yaw diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 6c46d1e..afd4acc 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -55,15 +55,35 @@ class MITRotorTurbine(BaseOperationModel): Turbine operation model as described by Liew et al. (2024). Args: - bem_model (BEM): optional BEM model as defined in MITRotor, defaults to IEA15MW with UMM momentum model - pitch_interp (interp1d): optional 1D or 2D interpolator for pitch trajectory based on wind speed, - if 1D by wind speed then yaw not accounted for, if 2D then wind speed and yaw accounted for. - Defaults to 1D IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf). - See ROSCOInterface.py for information on how to generate 2D control scheme interpolator. - tsr_interp (interp1d): optional 1D interpolator for tsr trajectory based on wind speed, - if 1D by wind speed then yaw not accounted for, if 2D then wind speed and yaw accounted for. - Defaults to IEA15MW Figure 2 (https://docs.nrel.gov/docs/fy22osti/82134.pdf). - See ROSCOInterface.py for information on how to generate 2D control scheme interpolator. + bem_model (BEM, optional): BEM model as defined in MITRotor. Defaults to the + IEA15MW rotor with the UMM momentum model. + + gen_eff (float, optional): Generator efficiency in percent [%]. + Defaults to 95.756. + + eff_ratio (float, optional): Optional efficiency ratio override (unitless). + If provided, this is used directly instead of deriving efficiency from + `gen_eff`. Defaults to None. + + pitch_interp (InterpLike, optional): 1D or 2D interpolator for pitch trajectory. + - 1D: function of wind speed only (yaw not accounted for) + - 2D: function of wind speed and yaw + Defaults to the 1D IEA15MW Figure 2 trajectory + (https://docs.nrel.gov/docs/fy22osti/82134.pdf). + See `ROSCOInterface.py` for generating a 2D control-scheme interpolator. + + pitch_rad (bool, optional): Whether the pitch interpolator uses radians (True) + or degrees (False). Defaults to True. + + tsr_interp (InterpLike, optional): 1D or 2D interpolator for TSR trajectory. + - 1D: function of wind speed only (yaw not accounted for) + - 2D: function of wind speed and yaw + Defaults to the IEA15MW Figure 2 trajectory + (https://docs.nrel.gov/docs/fy22osti/82134.pdf). + See `ROSCOInterface.py` for generating a 2D control-scheme interpolator. + + rated_rotor_speed (float, optional): Rated rotor speed [rad/s]. + Defaults to None. Methods: power diff --git a/MITRotor/Momentum.py b/MITRotor/Momentum.py index 50f1abd..1bc8582 100644 --- a/MITRotor/Momentum.py +++ b/MITRotor/Momentum.py @@ -126,12 +126,12 @@ def __init__(self, a = 1/3): self._func = self._func_rotor def compute_induction(self, Cx, yaw, tilt = 0) -> ArrayLike: - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the ConstantInduction momentum model. Use UMM.") return self.a * np.ones_like(yaw) def compute_initial_wake_velocities(self, Ct: float, yaw: float, tilt: float = 0.0) -> ArrayLike: - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the ConstantInduction momentum model. Use UMM.") u4 = 1 - 2 * self.a v4 = - (1/4) * Ct * np.sin(yaw) @@ -152,14 +152,14 @@ def __init__(self, averaging: Literal["sector", "annulus", "rotor"] = "rotor"): self.averaging = averaging def compute_induction(self, Cx, yaw, tilt = 0): - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the ClassicalMomentum momentum model. Use UMM.") Cx = np.asarray(Cx) sqrt_term = np.sqrt(np.where(Cx < 1, 1 - Cx, np.nan)) return 0.5 * (1 - sqrt_term) def compute_initial_wake_velocities(self, Ct: float, yaw: float, tilt: float = 0.0) -> ArrayLike: - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the ClassicalMomentum momentum model. Use UMM.") u4 = np.sqrt(1 - Ct) v4 = - (1/4) * Ct * np.sin(yaw) @@ -187,8 +187,8 @@ def __init__(self, def compute_induction(self, Cx: ArrayLike, yaw: float, tilt: float = 0.0) -> ArrayLike: - # if tilt != 0: - # raise ValueError("Tilt not supported by the Madsen momentum model. Use UMM.") + if np.any(tilt != 0): + raise ValueError("Tilt not supported by the Madsen momentum model. Use UMM.") if self.cosine_exponent: Ct = Cx / (np.cos(yaw)**2) else: @@ -198,7 +198,7 @@ def compute_induction(self, Cx: ArrayLike, yaw: float, tilt: float = 0.0) -> Arr return an def compute_initial_wake_velocities(self, Ct: float, yaw: float, tilt: float = 0.0) -> ArrayLike: - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the Madsen momentum model. Use UMM.") u4 = np.sqrt(np.maximum(1 - Ct, 0)) v4 = - (1/4) * Ct * np.sin(yaw) @@ -230,7 +230,7 @@ def __init__( self.averaging = averaging def compute_induction(self, Cx: ArrayLike, yaw: float, tilt: float = 0.0) -> ArrayLike: - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the HeckMomentum model for BEM. Use UMM.") Ctc = 4 * self.ac * (1 - self.ac) / (1 + 0.25 * (1 - self.ac) ** 2 * np.sin(yaw) ** 2) slope = (16 * (1 - self.ac) ** 2 * np.sin(yaw) ** 2 - 128 * self.ac + 64) / ( @@ -253,7 +253,7 @@ def compute_induction(self, Cx: ArrayLike, yaw: float, tilt: float = 0.0) -> Arr return a def compute_initial_wake_velocities(self, Ct: float, yaw: float, tilt: float = 0.0) -> ArrayLike: - if tilt != 0: + if np.any(tilt != 0): raise ValueError("Tilt not supported by the HeckMomentum model for BEM. Use UMM.") a = self.compute_induction(Ct, yaw) u4 = 1 - Ct /(2 * (1 - a)) diff --git a/examples/MITRotor_quickstart.ipynb b/examples/MITRotor_quickstart.ipynb index fc669fd..f0be3db 100644 --- a/examples/MITRotor_quickstart.ipynb +++ b/examples/MITRotor_quickstart.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -63,7 +63,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -94,7 +94,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -119,7 +119,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -163,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -186,7 +186,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -211,7 +211,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -230,7 +230,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 22, "metadata": {}, "outputs": [], "source": [ @@ -240,7 +240,7 @@ " tiploss_model = prandtl_tip_loss,\n", " momentum_model = unified_momentum_model,\n", " tangential_induction_model = tangential_induction_model,\n", - " aerodynamic_model = kragh_aerodynamic_model\n", + " aerodynamic_model = default_aerodynamic_model\n", ")" ] }, @@ -260,21 +260,21 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "BEM solution converged in 18 iterations.\n", + "BEM solution converged in 11 iterations.\n", "Control setpoints: sol.pitch=0.00, sol.tsr=7.00, sol.yaw=0.35\n", "Power coefficient: 0.39\n", - "Thrust coefficient: 0.60\n", - "Local thrust coefficient: 1.17\n", - "Axial induction: 0.24\n", + "Thrust coefficient: 0.58\n", + "Local thrust coefficient: 1.12\n", + "Axial induction: 0.23\n", "Rotor-effective windspeed: 1.00\n", - "Far-wake streamwise velocity: 0.64\n", + "Far-wake streamwise velocity: 0.65\n", "Far-wake lateral velocity: -0.05\n" ] } @@ -308,17 +308,17 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "<>:7: SyntaxWarning: invalid escape sequence '\\m'\n", - "<>:7: SyntaxWarning: invalid escape sequence '\\m'\n", - "/var/folders/dt/wzb0_01j5yz8q2y9bz5sfjm00000gn/T/ipykernel_16176/2546713841.py:7: SyntaxWarning: invalid escape sequence '\\m'\n", - " axes[-1].set_xlabel(\"Radial position, $\\mu$ [-]\")\n" + "SyntaxWarning: <>:7\n", + "invalid escape sequence '\\m'SyntaxWarning: <>:7\n", + "invalid escape sequence '\\m'SyntaxWarning: /var/folders/dt/wzb0_01j5yz8q2y9bz5sfjm00000gn/T/ipykernel_3191/2546713841.py:7\n", + "invalid escape sequence '\\m'" ] }, { @@ -327,13 +327,13 @@ "(0.0, 1.0)" ] }, - "execution_count": 11, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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WCQ9acHsxAAAAGCWSfyWLFlCGzduFFUa7owseeihhzT3e/ToQT179qSoqCix3ahRo657n7lz54p+P/VnOAQAAAAwqHLj7+9PDg4OlJWVpbOeHwcFBTX52hUrVohws337dhFemtKhQwfxs5KSkhp83tnZWTMbMWYlBgAAgBaHG4VCQX379hXNRxLuUMyPBw0a1Ojrli1bRosWLaKtW7dSv379mv05ly5dEn1ugoODDdk9AAAAAMOHgnNzEM9ds2HDBjpz5ozo/FtaWkpTp04Vz/MIKG42knAfmtdff53Wr18v5sbhvjm8lJSUiOf59sUXX6Q//viDUlNTRVAaO3YsRUdHiyHmAAAAACbtczN+/HjKycmhefPmiZDSq1cvUZGROhmnpaWJEVSSNWvWiFFW999/v8778Dw5CxYsEM1cf//9twhLPBycOxvzPDhc6eHmJwAAAACTznNjiTDPDQAAgPUpsoR5bgAAAAAsHcINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADICsINAAAAyArCDQAAAMgKwg0AAADISovCTXx8PEVERJCLiwvFxsbS4cOHG9123bp1NGzYMPLx8RHL6NGjm9x+2rRpZGdnRytXrmzJrgEAAICNMzjcbNq0iWbPnk3z58+no0ePUkxMDMXFxVF2dnaD2+/evZsmTJhAu3btooMHD1JYWBiNGTOGLl++fN22W7ZsoT/++INCQkJa9tsAAACAzbNTqVQqQ44CV2r69+9Pq1evFo+VSqUILLNmzaI5c+Y0+/ra2lpRweHXT5o0SbOeww6/97Zt2+iOO+6gZ599ViwNqaysFIukqKhI7ENhYSF5eXnZ/EkFAACwBvz57e3tbfTPb4MqN1VVVZSQkCCaljRvYG8vHnNVRh9lZWVUXV1Nvr6+mnUckB555BF68cUXqVu3bs2+x+LFi8XBkBYONgAAAADM0ZDDkJubKyovgYGBOuv58dmzZ/V6j5df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", + "image/png": "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po9qbTJhZUmJDlvizuHPXQlYvCcRKVn5hudkROGr24ZjZLsI9GgazJGFyW6dOXMG6enpCA0Nhbe3t8NVn0qJjQSb5ORkBAYGIiIiwtq7RKQpmTVoVlIRhpvL9GiavewwPimbtkECy4ujWqNhPW/VKHjx7jNIzLwwq6lUX13dJlw1DL6iaTBcbXSAQKKqXtwTExNVwHFkEmxksk1HC3dEtY3hpo4Pjp4M9Dd1wU4cSLx02gY/T1cMaV0aaHo3C4G7KwMNaVNxcTEKCy+0H3MkUhXl4mKdcbCItC6zFq7fbHNjhnYNA/D7pD6Yu/Io3vv3iAow0gZHejr1bRECD1d+6ZH2ycWdF3gisgeslqrGWDU66BhoiIiILIAlNzaA1U5ERES2jQ1EiIiISFNctTbAlhRvERERkX3QX7ctOVCmZsJNWlqauo2KirL2rhAREVE1ruPSa8oSNBNugoJKZ/M+efKkxQ4OVT+FS8iMj4+3eLd84rmwV/y9sC08H7ZDuoBHR0cbruOWoJlw4+xc2nxIgg0vqLZBzgPPhW3gubAdPBe2hefD9q7jFnkvi70TERERkQ1guCEiIiJN0Uy48fDwwIsvvqhuieeC+Htha/gdZVt4PrR9LjQzQjERERGRpkpuiIiIiATDDREREWkKww0RERFpCsMNERERaQrDDREREWkKww0RERFpCsMNERERaQrDDREREWkKww0RERFpCsMNERERaQrDDREREWkKww0RERFpCsMNERERaQrDDREREWmKKzSipKQECQkJ8PPzg5OTk7V3h4iIiMyg0+mQlZWFyMhIODtbpsxFM+FGgk1UVJS1d4OIiIiqIT4+Hg0bNoQlaCbcSImN/uD4+/tbe3eIiIjIDJmZmapwQn8dtwTNhBt9VZQEG4YbIiIi+2LJJiVsUExERESawnBDREREmsJwQ0RERJrCcENERESawnBDREREmsJwQ0RERJrCcENERESawnBDREREmsJwQ0RERJrCcENERESawnBDREREmsJwQ0RERJrCcENERESawnBDREREmsJwQ0RERJpSrXBz+vRprF+/HsnJyWZtX1xcjAMHDmD37t3Izc2tdFt5fsWKFdi7d291do2IiIgcXJXCTUlJCe655x40b94c999/P6Kjo/HUU09V+pr33nsPjRs3xpgxYzBu3DhERkbis88+q3D7SZMm4aqrrsKLL75YlV0jIiIiUlxRBe+//z5++eUX7Ny5Ey1atMDGjRvRt29fdOvWDTfccEO5r8nMzMTmzZsRHh6uHs+bNw8TJkxA165d0aFDB5Ntf/jhB/XegwYNqspuEREREVWv5EaCyY033qiCjejRowcGDx6s1lfkmWeeMQQbceedd8LV1VUFI2PHjh3D448/jm+//RZubm5V2S0iIiKiqocbaTcjbWa6dOlisl4eb9++3dy3wY4dO1BQUICYmBjDusLCQlVlNX36dMTGxpr1Pvn5+apUyHghIiIiMjvcZGVloaioCEFBQSbrQ0JCcO7cObPeIzs7G3fddRf69euH/v37G9ZPmzYNERERuO+++8w+IzNnzkRAQIBhiYqK4tkkIiIi88ONu7u7ur24t1NOTo7hucrk5eWpRsVSajN//nw4OTmp9dIeRxod33rrraqXlCxpaWlISUlR9+V15ZFAlJGRYVji4+N5OomIiMj8BsXe3t6qlEa6gRuTx40aNbpsFZIEGwkgElhCQ0NNnuvZs6dqrKx36NAhODs7q2oqaWRs3GZHz8PDQy1ERERExpx0Op0OZho/fjyOHz+uxrgRUk0lbWeuu+46zJo1S607ceIETp06hT59+pgEG3ndf//9p6qfLmfkyJHw9PTEggULzN011eZGqqekFMff39/s1xEREZH11Mb1u0pdwV944QXV7VvGupEA8s0336hqqSeeeMKwzRdffIHZs2cjPT1dPb7pppuwZs0afPLJJzh48KBahIx9IwsRERGRJVUp3LRs2VJ14X777bcxd+5cVWojj41LYySw6Ett9G10pEeVbG9MuoTLUp527dqZ1Y6HiIiIqEbVUraM1VJERET2pzau35w4k4iIiDSF4YaIiIg0heGGiIiINIXhhoiIiDSF4YaIiIg0heGGiIiINIXhhoiIiDSF4YaIiIg0heGGiIiINIXhhoiIiDSF4YaIiIg0heGGiIiINIXhhoiIiDSF4YaIiIg0heGGiIiINIXhhoiIiDSF4YaIiIg0heGGiIiINIXhhoiIiDSF4YaIiIg0heGGiIiINIXhhoiIiDTFFRqTU1AE14Iia+8GERERmXndtjTNhZvuryyHs4e3tXeDiIiIzFCSnwNLY7UUERERaYqTTqfTQQMyMzMREBCAMylp8Pf3t/buEBERkZnX74j6wcjIyLDY9Vtz1VLe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", "text/plain": [ "
" ] @@ -359,6 +359,145 @@ "source": [ "If you're looking for a more exploratory script, see `example_03_pitch_tsr_contour.py`. If you're looking to run a simulation with multiple turbines in a wind farm configuration, see the quick start guide for `MITWindfarm`." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Use with FLORIS\n", + "\n", + "MITRotor has a FLORIS interface so that MITRotor models can be used within FLORIS runs. A basic example of this is in the example `example_06_floris_integration.py`. \n", + "\n", + "The user can create a `MITRotorTurbine`, which is a child class of the FLORIS class, `BaseOperationModel`. The model is parameterized by an optional `bem_model` together with efficiency settings `gen_eff` (in %) which will be combined with the gearbox ratio to get the total efficiency ratio, `eff_ratio`. Control trajectories are provided through `pitch_interp` and `tsr_interp`, each of which may be either 1D in wind speed (no yaw dependence) or 2D in wind speed and yaw. The flag `pitch_rad` determines whether pitch interpolation inputs are interpreted in radians (otherwise degrees), and `rated_rotor_speed` optionally specifies the rated rotor speed in `rad/s`.\n", + "\n", + "An example of this is as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "DeprecationWarning: /Users/sky/Library/Caches/pypoetry/virtualenvs/mitrotor-l4Gn_-ln-py3.12/lib/python3.12/site-packages/scipy/interpolate/_interpolate.py:324\n", + "__array__ implementation doesn't accept a copy keyword, so passing copy=False failed. __array__ must implement 'dtype' and 'copy' keyword arguments. To learn more, see the migration guide https://numpy.org/devdocs/numpy_2_0_migration_guide.html#adapting-to-changes-in-the-copy-keywordUserWarning: /Users/sky/src/HowlandLab/MITRotor/MITRotor/FlorisInterface/InterfaceUtilities.py:52\n", + "Using 1D control curve with nonzero yaw/tilt; yaw/tilt is ignored for lookup." + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Powers [W]:\n", + " [[ 6459808.16959411 1286595.70487608]\n", + " [12616812.83118355 2756681.50823379]\n", + " [14976393.19316245 15070208.06388656]] \n", + "\n", + "Thrust coefficients [-]:\n", + " [[0.77745948 0.7792296 ]\n", + " [0.77745948 0.78725775]\n", + " [0.42307743 0.49466813]] \n", + "\n", + "Axial induction factors [-]:\n", + " [[0.32727575 0.31936816]\n", + " [0.32727575 0.32933065]\n", + " [0.15925286 0.18696097]] \n", + "\n" + ] + } + ], + "source": [ + "from floris import FlorisModel, TimeSeries\n", + "from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine\n", + "from MITRotor.FlorisInterface.InterfaceUtilities import query_controls\n", + "\n", + "fmodel = FlorisModel(\"defaults\")\n", + "time_series = TimeSeries(\n", + " wind_directions=np.array([270.0, 270.0, 280.0]),\n", + " wind_speeds=np.array([8.0, 10.0, 12.0]),\n", + " turbulence_intensities=np.array([0.06, 0.06, 0.06]),\n", + ")\n", + "yaw_angles = np.array([\n", + " [0.0, 0.0], # condition 1\n", + " [0.0, 0.0], # condition 2\n", + " [0.0, 0.0], # condition 3\n", + "])\n", + "\n", + "fmodel.set(\n", + " layout_x = [0.0, 500.0],\n", + " layout_y = [0.0, 0.0],\n", + " wind_data = time_series,\n", + " yaw_angles = yaw_angles\n", + ")\n", + "\n", + "mit_rotor_turbine = MITRotorTurbine(bem_model = bem_model)\n", + "fmodel.set_operation_model(mit_rotor_turbine)\n", + "\n", + "fmodel.run()\n", + "print(\"Powers [W]:\\n\", fmodel.get_turbine_powers(), \"\\n\")\n", + "print(\"Thrust coefficients [-]:\\n\", fmodel.get_turbine_thrust_coefficients(), \"\\n\")\n", + "print(\"Axial induction factors [-]:\\n\", fmodel.get_turbine_axial_induction_factors(), \"\\n\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case, the blade pitch and TSR curves are the default curves, which can be seen here:" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "wind_speed_vals = np.linspace(3, 25, 50)\n", + "mit_rotor_turbine.pitch_interp\n", + "blade_pitch_vals = query_controls(mit_rotor_turbine.pitch_interp, wind_speed_vals, yaw_rad = 0)\n", + "tsr_vals = query_controls(mit_rotor_turbine.tsr_interp, wind_speed_vals, yaw_rad = 0)\n", + "\n", + "fig, ax = plt.subplots()\n", + "ax.plot(wind_speed_vals, np.rad2deg(blade_pitch_vals), label = \"Pitch [deg]\")\n", + "ax.plot(wind_speed_vals, tsr_vals, label = \"Tip-Speed Ratio [-]\")\n", + "ax.set_title(\"IEA 15MW: Fixed Bottom Trajectories\", size = 18)\n", + "ax.set_xlabel(\"Wind Speed [m/s]\", size = 16)\n", + "ax.tick_params(labelsize=14)\n", + "ax.legend(fontsize = 14)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The user can also provide their own blade pitch and TSR interpolators. These can either be 1D and just take in wind speeds, or 2D and take in wind speeds and yaw (or effective yaw, which is the combination of yaw and tilt). \n", + "\n", + "MITRotor also provides a ROSCO interface, which aids in the creation of these 2D interpolators using existing control strategies. `example_08_floris_rosco.py` gives an example of how to generate new control scheme interpolators using the function `get_rosco_control_interps`.\n" + ] } ], "metadata": { diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index f3ebe3d..2a8b48d 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -87,15 +87,15 @@ def main(): # takes ~25min with 8 workers rosco_VS_1_pitch_interp, rosco_VS_1_tsr_interp, rosco_VS_1_rated_rotorspeed = get_rosco_control_interps( rosco_yaml_VS_1, bem, - regenerate = False, save_control_file = "control_vs_1.csv") - # regenerate = True, save_control_file = "control_vs_1.csv") + # regenerate = False, save_control_file = "control_vs_1.csv") + regenerate = True, save_control_file = "control_vs_1.csv") end = time.time() print(f"Time to make control CSV: {end - start}") # takes ~25min with 8 workers rosco_VS_3_pitch_interp, rosco_VS_3_tsr_interp, rosco_VS_3_rated_rotorspeed = change_control_param( "VS_ControlMode", 3, rosco_yaml_VS_1, bem, - # regenerate = True, save_control_file = "control_vs_3.csv", - regenerate = False, save_control_file = "control_vs_3.csv" + regenerate = True, save_control_file = "control_vs_3.csv", + # regenerate = False, save_control_file = "control_vs_3.csv" ) # Plot IEA15MW control from ROSCO paper, ROSOC control with VS_Control_Mode = 1, and ROSOC control withVS_Control_Mode = 3 From 63daecce5611b8f20cd34471085f23c8ed5ed245 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Mon, 3 Aug 2026 09:28:49 -0400 Subject: [PATCH 43/50] Remove repetative example --- examples/example_timing.py | 129 ------------------------------- examples/example_timing_plots.py | 96 ----------------------- 2 files changed, 225 deletions(-) delete mode 100644 examples/example_timing.py delete mode 100644 examples/example_timing_plots.py diff --git a/examples/example_timing.py b/examples/example_timing.py deleted file mode 100644 index 169e3d7..0000000 --- a/examples/example_timing.py +++ /dev/null @@ -1,129 +0,0 @@ -import numpy as np -from pathlib import Path -from MITRotor.Momentum import UnifiedMomentumLUT, UnifiedMomentum -from MITRotor.TipLoss import NoTipLoss -from MITRotor import BEM, IEA15MW, BEMGeometry -import pandas as pd -import time - -# Floris imports -from floris import FlorisModel, TimeSeries -from MITRotor.FlorisInterface.FlorisInterface import MITRotorTurbine, default_bem_factory - -bem_rotor_umm = default_bem_factory() -bem_annulus_umm_LUT = BEM( - rotor=IEA15MW(), - momentum_model=UnifiedMomentumLUT(averaging="annulus", cache_fn = Path("cache")/ "lut.csv"), - geometry=BEMGeometry(Nr=10, Ntheta=20), - tiploss_model=NoTipLoss(), -) -rotor_area = np.pi * bem_rotor_umm.rotor.R**2 - -bem_rotor_times = [] -bem_annulus_LUT_times = [] -wind_speeds_all = [] -bem_rotor_values = [] -bem_annulus_LUT_values = [] -ns = [5 * i for i in range(1, 21)] -for n in ns: - print(f"{n} wind speeds") - wind_speeds = np.linspace(5, 20, n) - wind_dirs = np.full_like(wind_speeds, 270.0) - turbulence_intensity = np.zeros_like(wind_speeds) - wind_speeds_all.extend( - np.squeeze(wind_speeds) - ) - - time_series = TimeSeries( - wind_speeds=wind_speeds, - wind_directions=wind_dirs, - turbulence_intensities=turbulence_intensity, - ) - - fmodel_rotor_umm = FlorisModel("defaults") - fmodel_rotor_umm.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) - fmodel_rotor_umm.set_operation_model(MITRotorTurbine(bem_model = bem_rotor_umm)) # default bem_model uses rotor-averaging - floris_rotor_umm_start = time.time() - fmodel_rotor_umm.run() - floris_rotor_umm_end = time.time() - dt_rotor = floris_rotor_umm_end - floris_rotor_umm_start - print("FLORIS UMM-BEM Rotor-Averaged: " + str(dt_rotor) + " seconds") - bem_rotor_times.append(dt_rotor) - floris_Cp_rotor_umm = np.squeeze(fmodel_rotor_umm.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) - bem_rotor_values.extend( - np.squeeze(floris_Cp_rotor_umm) - ) - - # solve FLORIS with UMM-BEM with LUT though MITRotor - annulus averaged - fmodel_annulus_umm_LUT = FlorisModel("defaults") - fmodel_annulus_umm_LUT.set(layout_x = [0.0], layout_y = [0.0], wind_data = time_series) - fmodel_annulus_umm_LUT.set_operation_model(MITRotorTurbine(bem_model = bem_annulus_umm_LUT)) # default bem_model uses rotor-averaging - floris_annulus_umm_LUT_start = time.time() - fmodel_annulus_umm_LUT.run() - floris_annulus_umm_LUT_end = time.time() - dt_annulus_LUT = floris_annulus_umm_LUT_end - floris_annulus_umm_LUT_start - print("FLORIS UMM-BEM LUT Annulus-Averaged: " + str(dt_annulus_LUT) + " seconds") - bem_annulus_LUT_times.append(dt_annulus_LUT) - floris_Cp_annulus_umm_LUT = np.squeeze(fmodel_annulus_umm_LUT.get_turbine_powers()) / (0.5 * 1.225 * rotor_area * (wind_speeds)**3) - bem_annulus_LUT_values.extend( - np.squeeze(floris_Cp_annulus_umm_LUT) - ) - -# make timing CSV -vectorized = False -rows = [] - -for n, dt in zip(ns, bem_rotor_times): - rows.append({ - "n_wind_speeds": n, - "runtime_seconds": dt, - "model": "rotor_umm", - "vectorized": vectorized - }) - -for n, dt in zip(ns, bem_annulus_LUT_times): - rows.append({ - "n_wind_speeds": n, - "runtime_seconds": dt, - "model": "annulus_lut", - "vectorized": vectorized - }) - -df = pd.DataFrame(rows) - -csv_path = Path("cache")/ "timing_results.csv" - -if csv_path.exists(): - df.to_csv(csv_path, mode="a", header=False, index=False) -else: - df.to_csv(csv_path, index=False) - -# make values CSV -rows = [] -# Rotor -for wind, val in zip(wind_speeds_all, bem_rotor_values): - rows.append({ - "wind_speed": wind, - "power": val, - "model": "rotor_umm", - "vectorized": vectorized - }) - -# Annulus LUT -for wind, val in zip(wind_speeds_all, bem_annulus_LUT_values): - rows.append({ - "wind_speed": wind, - "power": val, - "model": "annulus_lut", - "vectorized": vectorized - }) - -df = pd.DataFrame(rows) - -csv_path = Path("cache") / "value_results.csv" - -if csv_path.exists(): - df.to_csv(csv_path, mode="a", header=False, index=False) -else: - df.to_csv(csv_path, index=False) - diff --git a/examples/example_timing_plots.py b/examples/example_timing_plots.py deleted file mode 100644 index 0bc9835..0000000 --- a/examples/example_timing_plots.py +++ /dev/null @@ -1,96 +0,0 @@ -import pandas as pd -import matplotlib.pyplot as plt -from pathlib import Path - -# ---- Load data ---- -figdir = Path("fig") -time_df = pd.read_csv(Path("cache")/ "timing_results.csv") -value_df = pd.read_csv(Path("cache")/ "value_results.csv") - -#------------------------------------ -# Timing plot -#------------------------------------ -df_avg = ( - time_df.groupby(["n_wind_speeds", "model", "vectorized"], as_index=False) - .agg( - runtime_mean=("runtime_seconds", "mean"), - runtime_std=("runtime_seconds", "std"), - ) -) - -# ---- Create label column for plotting ---- -def make_label(row): - base = { - "rotor_umm": "UMM Rotor-Averaged", - "annulus_lut": "UMM LUT Annulus-Averaged", - }[row["model"]] - - if row["vectorized"]: - return base + " (Vectorized)" - else: - return base - -df_avg["label"] = df_avg.apply(make_label, axis=1) - -label_order = [ - "UMM Rotor-Averaged", - "UMM LUT Annulus-Averaged", - "UMM Rotor-Averaged (Vectorized)", - "UMM LUT Annulus-Averaged (Vectorized)", -] - -# ---- Plot ---- -plt.figure(figsize=(6, 4)) - -for label in label_order: - group = df_avg[df_avg["label"] == label] - group = group.sort_values("n_wind_speeds") - - plt.errorbar( - group["n_wind_speeds"], - group["runtime_mean"], - yerr=group["runtime_std"], - marker="o", - capsize=3, - label=label, - linewidth = 2, - ) - # plt.yscale("log") - -plt.xlabel("Number of Wind Speeds Run\n(evenly-spaced between 5-20 m/s)") -plt.ylabel("Runtime (seconds)") -plt.title("Runtime vs Number of Wind Speeds") -plt.legend() -plt.grid(True) -plt.tight_layout() -plt.savefig(figdir / "example_timings.png", dpi=300) - -#------------------------------------ -# Value plot -#------------------------------------ -plt.figure(figsize=(6, 4)) - -value_df["label"] = value_df.apply(make_label, axis=1) - -for label in label_order: - group = value_df[value_df["label"] == label] - group = group.sort_values("wind_speed") - is_vectorized = group["vectorized"].iloc[0] - linestyle = "dashed" if is_vectorized else "solid" - zorder = 2 if is_vectorized else 1 - plt.plot( - group["wind_speed"], - group["power"], - linewidth = 3, - label=label, - linestyle = linestyle, - zorder = zorder, - ) - -plt.xlabel("Wind Speed [m/s]") -plt.ylabel("Coefficent of Power ($C_P$)") -plt.title("$C_P$ vs Wind Speed") -plt.legend() -plt.grid(True) -plt.tight_layout() -plt.savefig(figdir / "example_values.png", dpi=300) \ No newline at end of file From 516d960405782afd00aa627967193fd099693fad Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 7 Aug 2026 10:19:31 -0400 Subject: [PATCH 44/50] Remove x0 --- MITRotor/FlorisInterface/FlorisInterface.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index afd4acc..dc5c2a2 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -108,7 +108,6 @@ class MITRotorTurbine(BaseOperationModel): _u4 = field(init=False, default=None, type = NDArrayFloat) _v4 = field(init=False, default=None, type = NDArrayFloat) _w4 = field(init=False, default=None, type = NDArrayFloat) - _x0 = field(init=False, default=None, type = NDArrayFloat) _power = field(init=False, default=None, type = NDArrayFloat) # calculate a few needed fields post-initialization @@ -148,7 +147,6 @@ def _update_solution(self, self._u4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._v4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._w4 = np.empty((n_findex, n_turbines), dtype=floris_float_type) - self._x0 = np.empty((n_findex, n_turbines), dtype=floris_float_type) self._power = np.empty((n_findex, n_turbines), dtype=floris_float_type) # compute the power-effective wind speed across the rotor @@ -184,8 +182,7 @@ def _update_solution(self, # get near wake velocities self._u4[:, tindex] = bem_sol.u4 self._v4[:, tindex] = bem_sol.v4 - self._w4[:, tindex] = bem_sol.w4 - self._x0[:, tindex] = bem_sol.x0 + self._w4[:, tindex] = bem_sol.w4 # compute power self._power[:, tindex] = ( 0.5 * bem_sol.Cp() * air_density * rotor_area @@ -208,4 +205,4 @@ def axial_induction(self, **kwargs) -> NDArrayFloat: def near_wake_velocities(self, **kwargs) -> NDArrayFloat: self._update_solution(**kwargs) - return (self._u4, self._v4, self._w4, self._x0) \ No newline at end of file + return (self._u4, self._v4, self._w4) \ No newline at end of file From b2a1b8d7c3859548eb2582d0e32acf0fe43821cf Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Fri, 7 Aug 2026 16:51:30 -0400 Subject: [PATCH 45/50] Updated for PR --- MITRotor/FlorisInterface/FlorisInterface.py | 1 + .../FlorisInterface/InterfaceUtilities.py | 16 ++-- MITRotor/FlorisInterface/ROSCOInterface.py | 73 ++++++++++--------- examples/example_08_floris_rosco.py | 18 +++-- 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index dc5c2a2..29d9d59 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -89,6 +89,7 @@ class MITRotorTurbine(BaseOperationModel): power thrust_coefficient axial_induction + near_wake_velocities """ # user can define a BEM model if they want a different rotor, momentum model, or geometry bem_model = field(init = True, factory = default_bem_factory, type = BEM) diff --git a/MITRotor/FlorisInterface/InterfaceUtilities.py b/MITRotor/FlorisInterface/InterfaceUtilities.py index a954fe5..8a976fe 100644 --- a/MITRotor/FlorisInterface/InterfaceUtilities.py +++ b/MITRotor/FlorisInterface/InterfaceUtilities.py @@ -147,7 +147,7 @@ def run_yaw_row_sim(v_grid, yaw_grid_rad, yaw_row_func, n_jobs): def _run_serial(desc): out = [] - for i, yaw_rad in enumerate(tqdm(yaw_grid_rad, total=n_wind, desc=desc, dynamic_ncols=True)): + for i, yaw_rad in enumerate(tqdm(yaw_grid_rad, total=n_yaw, desc=desc, dynamic_ncols=True)): out.append(yaw_row_func(i, yaw_rad)) return out @@ -202,7 +202,7 @@ def __init__( init_gen_speed=1.0, # rad/s init_pitch_deg=0.0, # deg init_torque=0.0, # Nm - init_nac_imu=0.0, # rad + init_yaw_rad=0.0, # rad **kwargs ): """ @@ -224,8 +224,8 @@ def __init__( Initial collective blade pitch, in degrees. init_torque : float, optional Initial generator torque, in Nm. - init_nac_imu : float, optional - Initial nacelle IMU angle/state, in radians. + init_yaw_rad : float, optional + Initial yaw angle/state, in radians. **kwargs Additional keyword arguments forwarded to `ROSCO_ci.ControllerInterface` (e.g., `DT`, `sim_name`, etc.). @@ -235,7 +235,7 @@ def __init__( self.init_rot_speed = float(init_rot_speed) self.init_gen_speed = float(init_gen_speed) self.init_torque = float(init_torque) - self.init_nac_imu = float(init_nac_imu) + self.init_yaw_rad = float(init_yaw_rad) # Parent uses self.pitch for initial blade pitch super().__init__( @@ -271,7 +271,7 @@ def init_discon(self): # --- warm-start initial states (replaces hard-coded values) --- self.avrSWAP[19] = self.init_gen_speed # gen speed [rad/s] self.avrSWAP[20] = self.init_rot_speed # rot speed [rad/s] - self.avrSWAP[82] = self.init_nac_imu # nac IMU + self.avrSWAP[82] = 0 # HARD CODE initial nacIMU = 0 self.avrSWAP[26] = self.init_ws # wind speed [m/s] self.avrSWAP[22] = self.init_torque # gen torque [Nm] @@ -282,6 +282,10 @@ def init_discon(self): self.avrSWAP[32] = pitch_rad self.avrSWAP[33] = pitch_rad + # Initial yaw + self.avrSWAP[23] = self.init_yaw_rad + self.avrSWAP[36] = self.init_yaw_rad + self.avrSWAP[27] = 1 # IPC flag # First-call init diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 7f479a1..2b07181 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -131,12 +131,12 @@ def get_rosco_control_interps( save_control_file=None, save_dir=".", dt=0.05, - yaw_grid_deg=np.arange(0.0, 25.0, 1.0), # degrees + yaw_grid_deg=np.arange(-25.0, 25.0, 1.0), # degrees n_jobs=-1, # parallel workers across wind speeds ): """ Creates pitch and tsr 2D interpolators using ROSCO controller tuning. - Parallelized over yaws; wind speeds for each yaw are solved sequentially in one worker with warm-start chaining. + Parallelized over yaws; wind speeds for each yaw are solved sequentially. Args: rosco_yaml (str): Path to ROSCO controller YAML configuration file. @@ -175,10 +175,17 @@ def get_rosco_control_interps( ) if (controller_params["VS_ControlMode"] == 2): warnings.warn( - "We suggest NOT using VS_ControlMode = 2 within the control parameter file. Mismatched TSR definitions between MITRotor and" \ - "ROSCO lead to biased optimization.", - UserWarning, - ) + "We suggest NOT using VS_ControlMode = 2 within the control parameter file. Mismatched TSR definitions between MITRotor and" \ + "ROSCO lead to biased optimization.", + UserWarning, + ) + + if (controller_params["Y_ControlMode"] != 0): + warnings.warn( + "We suggest ONLY using Y_ControlMode = 0 within the control parameter file. This turns off yaw control," \ + "which is vital for keeping a steady yaw to determine yawed control setpoints.", + UserWarning, + ) # Generate turbine Cp/Ct surfaces turbine = load_from_mitrotor( @@ -268,33 +275,30 @@ def _run_one_yaw_row( nv = len(v_grid) pitch_col = np.full(nv, np.nan, dtype=float) tsr_col = np.full(nv, np.nan, dtype=float) - power_col = np.full(nv, np.nan, dtype=float)\ - - j = 0 - init_pitch_rad = init_pitch_rad_list[j] - init_pitch_deg = np.rad2deg(init_pitch_rad) - init_tsr = init_tsr_list[j] - init_rot_speed = init_tsr * v_grid[j] / turbine_sim.rotor_radius - init_gen_speed = init_rot_speed * turbine_sim.Ng - - controller_int = iu.WarmStartControllerInterface( - lib_name, - param_filename=param_filename, - sim_name=f"{SimName}_{i}_{j}", - DT=dt, - init_ws=v_grid[j], - init_rot_speed=init_rot_speed, - init_gen_speed=init_gen_speed, - init_pitch_deg=init_pitch_deg, # deg - init_torque=0.0, - init_nac_imu=yaw_rad, # rad - ) - - # lightweight sim object compatible with sim_ws_mitrotor - sim = SimpleNamespace(turbine=turbine_sim, controller_int=controller_int) + power_col = np.full(nv, np.nan, dtype=float) for j, v in enumerate(v_grid): - controller_int = None + init_pitch_rad = init_pitch_rad_list[j] + init_pitch_deg = np.rad2deg(init_pitch_rad) + init_tsr = init_tsr_list[j] + init_rot_speed = init_tsr * v / turbine_sim.rotor_radius + init_gen_speed = init_rot_speed * turbine_sim.Ng + + controller_int = iu.WarmStartControllerInterface( + lib_name, + param_filename=param_filename, + sim_name=f"{SimName}_{i}_{j}", + DT=dt, + init_ws=v, + init_rot_speed=init_rot_speed, + init_gen_speed=init_gen_speed, + init_pitch_deg=init_pitch_deg, # deg + init_torque=0.0, + init_yaw_rad=yaw_rad, # rad + ) + # lightweight sim object compatible with sim_ws_mitrotor + sim = SimpleNamespace(turbine=turbine_sim, controller_int=controller_int) + try: converged = sim_ws_mitrotor( sim=sim, bem=bem, ws=v, dt=dt, @@ -314,11 +318,12 @@ def _run_one_yaw_row( except Exception: continue - # Kill controller - sim.controller_int.kill_discon() - return i, pitch_col, tsr_col, power_col + finally: + # Kill controller - runs no matter what (success, failure, exception) + sim.controller_int.kill_discon() + return i, pitch_col, tsr_col, power_col # ----------------------------- # Steady-state simulation diff --git a/examples/example_08_floris_rosco.py b/examples/example_08_floris_rosco.py index 2a8b48d..1694c1a 100644 --- a/examples/example_08_floris_rosco.py +++ b/examples/example_08_floris_rosco.py @@ -22,7 +22,10 @@ figdir = Path("fig") -def change_control_param(param_key, param_value, template_yaml, bem, regenerate = False, save_control_file = "control.csv"): +def change_control_param( + param_key, param_value, template_yaml, bem, + regenerate = False, save_control_file = "control.csv", yaw_grid_deg = np.linspace(-25.0,25.0,50), +): yaml = YAML() with tempfile.TemporaryDirectory() as tmpdir: temp_yaml = Path(tmpdir) / "rosco_temp.yaml" @@ -37,7 +40,7 @@ def change_control_param(param_key, param_value, template_yaml, bem, regenerate pitch_interp, tsr_interp, rated_rotor_speed = get_rosco_control_interps( temp_yaml, bem, - regenerate = regenerate, save_control_file = save_control_file, + regenerate = regenerate, save_control_file = save_control_file, yaw_grid_deg = yaw_grid_deg ) return pitch_interp, tsr_interp, rated_rotor_speed @@ -51,6 +54,7 @@ def main(): # wind condtions wind_speeds = np.linspace(3, 25, 25) wind_dirs = np.full_like(wind_speeds, 270.0) + yaws_degs = np.linspace(-25.0,25.0,50) turbulence_intensity = np.zeros_like(wind_speeds) time_series = TimeSeries( wind_speeds=wind_speeds, @@ -76,7 +80,7 @@ def main(): cache_fn=cache_file, regenerate=False, LUT_Cts=np.linspace(-0.5,1.5,40), - LUT_yaws=np.linspace(0.0,40.0,40), + LUT_yaws=yaws_degs, # Note here that we are only allowing for yaws <25 degrees! Update if needed! ) print("LUT for BEM done generating. ") bem = BEM(rotor = IEA15MW(), momentum_model = lut_model, geometry = BEMGeometry(Nr=10, Ntheta=20)) @@ -87,15 +91,17 @@ def main(): # takes ~25min with 8 workers rosco_VS_1_pitch_interp, rosco_VS_1_tsr_interp, rosco_VS_1_rated_rotorspeed = get_rosco_control_interps( rosco_yaml_VS_1, bem, - # regenerate = False, save_control_file = "control_vs_1.csv") - regenerate = True, save_control_file = "control_vs_1.csv") + regenerate = False, save_control_file = "control_vs_1.csv", + yaw_grid_deg=yaws_degs + ) + end = time.time() print(f"Time to make control CSV: {end - start}") # takes ~25min with 8 workers rosco_VS_3_pitch_interp, rosco_VS_3_tsr_interp, rosco_VS_3_rated_rotorspeed = change_control_param( "VS_ControlMode", 3, rosco_yaml_VS_1, bem, regenerate = True, save_control_file = "control_vs_3.csv", - # regenerate = False, save_control_file = "control_vs_3.csv" + yaw_grid_deg=yaws_degs ) # Plot IEA15MW control from ROSCO paper, ROSOC control with VS_Control_Mode = 1, and ROSOC control withVS_Control_Mode = 3 From 320a9d90b0b9f228cf8acb5d7f6b40b6f167c4f8 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Tue, 11 Aug 2026 14:29:00 -0400 Subject: [PATCH 46/50] Remove unneeded x0 additions --- MITRotor/BEMSolver.py | 2 +- MITRotor/Momentum.py | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/MITRotor/BEMSolver.py b/MITRotor/BEMSolver.py index 61fe54c..b7984ce 100644 --- a/MITRotor/BEMSolver.py +++ b/MITRotor/BEMSolver.py @@ -247,7 +247,7 @@ def post_process(self, result: FixedPointIterationResult, pitch, tsr, yaw = 0, U aero_props = self.aerodynamic_model(an, aprime, pitch, tsr, yaw, self.rotor, self.geometry, U, wdir, tilt = tilt) aero_props.F = self.tiploss_model(aero_props, pitch, tsr, yaw, self.rotor, self.geometry, tilt = tilt) avg_Ct = average(self.geometry, aero_props.C_x) - u4,v4,w4,x0 = self.momentum_model.compute_initial_wake_velocities_and_x0(avg_Ct, yaw, tilt = tilt) + u4,v4,w4 = self.momentum_model.compute_initial_wake_velocities(avg_Ct, yaw, tilt = tilt) if self.scalar_inputs: # if all setpoints were scalars # return single values as scalars diff --git a/MITRotor/Momentum.py b/MITRotor/Momentum.py index 1bc8582..fe3d41c 100644 --- a/MITRotor/Momentum.py +++ b/MITRotor/Momentum.py @@ -46,12 +46,6 @@ def compute_induction(self, Cx: ArrayLike, yaw: float = 0, tilt:float = 0) -> Ar @abstractmethod def compute_initial_wake_velocities(self, Ct: float, yaw: float = 0, tilt: float = 0.0) -> ArrayLike: ... - - def compute_initial_wake_velocities_and_x0( - self, Ct: float, yaw: float = 0, tilt: float = 0.0 - ) -> ArrayLike: - return (*self.compute_initial_wake_velocities(Ct, yaw, tilt), None) - def _func_rotor( self, @@ -295,11 +289,6 @@ def compute_initial_wake_velocities(self, Cx: ArrayLike, yaw: float = 0.0, tilt: sol = self.model_Ct(Cx, yaw = yaw, tilt = tilt) return sol.u4, sol.v4, sol.w4 - def compute_initial_wake_velocities_and_x0(self, Cx: ArrayLike, yaw: float = 0.0, tilt: float = 0.0) -> ArrayLike: - sol = self.model_Ct(Cx, yaw = yaw, tilt = tilt) - return sol.u4, sol.v4, sol.w4, sol.x0 - - # Look-up table for unified model def func_Ct(x, beta, cached) -> dict: From 10f0f39c8b72996c665707cf99fd6d313a3613fd Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Tue, 11 Aug 2026 14:41:43 -0400 Subject: [PATCH 47/50] Remove excess x0 field --- MITRotor/BEMSolver.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MITRotor/BEMSolver.py b/MITRotor/BEMSolver.py index b7984ce..87f64d6 100644 --- a/MITRotor/BEMSolver.py +++ b/MITRotor/BEMSolver.py @@ -46,7 +46,6 @@ class BEMSolution: v4: float tilt: float = 0.0 w4: float = 0 - x0: float = 0 def a(self, grid: Literal["sector", "annulus", "rotor"] = "rotor"): return average(self.geom, self.aero_props.an, grid) @@ -262,4 +261,4 @@ def post_process(self, result: FixedPointIterationResult, pitch, tsr, yaw = 0, U if isinstance(value, np.ndarray): setattr(aero_props, key, np.squeeze(value)) - return BEMSolution(pitch, tsr, yaw, aero_props, self.geometry, result.converged, result.niter, u4, v4, tilt = tilt, w4 = w4, x0 = x0) + return BEMSolution(pitch, tsr, yaw, aero_props, self.geometry, result.converged, result.niter, u4, v4, tilt = tilt, w4 = w4) From 8ecfa37df337f14cf6dd68312d328d9f5b356063 Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Tue, 11 Aug 2026 17:37:19 -0400 Subject: [PATCH 48/50] Adjusted for feedback --- MITRotor/FlorisInterface/FlorisInterface.py | 2 +- MITRotor/FlorisInterface/ROSCOInterface.py | 2 +- poetry.lock | 841 +++++++++++--------- pyproject.toml | 13 +- tests/test_bem.py | 29 + 5 files changed, 484 insertions(+), 403 deletions(-) diff --git a/MITRotor/FlorisInterface/FlorisInterface.py b/MITRotor/FlorisInterface/FlorisInterface.py index 29d9d59..e8066cc 100644 --- a/MITRotor/FlorisInterface/FlorisInterface.py +++ b/MITRotor/FlorisInterface/FlorisInterface.py @@ -175,7 +175,7 @@ def _update_solution(self, # solve BEM for setpoints from control curves for tindex in range(n_turbines): - # solve BEM + # solve BEM - NOTE: could add in additional keywords U and wdir bem_sol = self.bem_model(pitch[:, tindex], tsr[:, tindex], yaw = yaw[:, tindex], tilt = tilt[:, tindex]) # get induction and thrust coeff self._a[:, tindex] = bem_sol.a() diff --git a/MITRotor/FlorisInterface/ROSCOInterface.py b/MITRotor/FlorisInterface/ROSCOInterface.py index 2b07181..8a6a479 100644 --- a/MITRotor/FlorisInterface/ROSCOInterface.py +++ b/MITRotor/FlorisInterface/ROSCOInterface.py @@ -65,7 +65,7 @@ def load_from_mitrotor( turbine.yaw = yaw turbine.tilt = tilt - # Calcualte remining needed values + # Calculate remining needed values turbine.rotor_radius = bem.rotor.R turbine.J = turbine.rotor_inertia + turbine.generator_inertia * turbine.Ng**2 turbine.rated_torque = turbine.rated_power/(turbine.GenEff/100*turbine.rated_rotor_speed*turbine.Ng) diff --git a/poetry.lock b/poetry.lock index f12c5b7..486c4ff 100644 --- a/poetry.lock +++ b/poetry.lock @@ -147,7 +147,7 @@ version = "26.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.9" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, @@ -265,7 +265,7 @@ version = "5.2.3" description = "The fastest memoizing and caching Python library written in Rust" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "cachebox-5.2.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c2c89720547271d36e10cad2c7302bbe11f46eb39eead0a2c321c2d371b8f8b6"}, {file = "cachebox-5.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7f33d24e90dc8aa26762e25898c91a1223b66685420a28a3628fa2e006924f5"}, @@ -387,7 +387,7 @@ version = "2026.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775"}, {file = "certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55"}, @@ -395,114 +395,114 @@ files = [ [[package]] name = "cffi" -version = "2.1.0" +version = "2.1.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.10" -groups = ["main", "dev"] -files = [ - {file = "cffi-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0"}, - {file = "cffi-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd"}, - {file = "cffi-2.1.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46"}, - {file = "cffi-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2"}, - {file = "cffi-2.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd"}, - {file = "cffi-2.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3"}, - {file = "cffi-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0"}, - {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43"}, - {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c"}, - {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd"}, - {file = "cffi-2.1.0-cp310-cp310-win32.whl", hash = "sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f"}, - {file = "cffi-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da"}, - {file = "cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc"}, - {file = "cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7"}, - {file = "cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93"}, - {file = "cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2"}, - {file = "cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c"}, - {file = "cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f"}, - {file = "cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565"}, - {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c"}, - {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02"}, - {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e"}, - {file = "cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479"}, - {file = "cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458"}, - {file = "cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d"}, - {file = "cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f"}, - {file = "cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde"}, - {file = "cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d"}, - {file = "cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7"}, - {file = "cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b"}, - {file = "cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7"}, - {file = "cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66"}, - {file = "cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe"}, - {file = "cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b"}, - {file = "cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a"}, - {file = "cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384"}, - {file = "cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6"}, - {file = "cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda"}, - {file = "cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b"}, - {file = "cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a"}, - {file = "cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea"}, - {file = "cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db"}, - {file = "cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f"}, - {file = "cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d"}, - {file = "cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0"}, - {file = "cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224"}, - {file = "cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c"}, - {file = "cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a"}, - {file = "cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2"}, - {file = "cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512"}, - {file = "cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f"}, - {file = "cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a"}, - {file = "cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3"}, - {file = "cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d"}, - {file = "cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac"}, - {file = "cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6"}, - {file = "cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913"}, - {file = "cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d"}, - {file = "cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5"}, - {file = "cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce"}, - {file = "cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326"}, - {file = "cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd"}, - {file = "cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb"}, - {file = "cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804"}, - {file = "cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714"}, - {file = "cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376"}, - {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98"}, - {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13"}, - {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d"}, - {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056"}, - {file = "cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4"}, - {file = "cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94"}, - {file = "cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76"}, - {file = "cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5"}, - {file = "cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8"}, - {file = "cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c"}, - {file = "cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001"}, - {file = "cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3"}, - {file = "cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc"}, - {file = "cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699"}, - {file = "cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022"}, - {file = "cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0"}, - {file = "cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1"}, - {file = "cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28"}, - {file = "cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629"}, - {file = "cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6"}, - {file = "cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853"}, - {file = "cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda"}, - {file = "cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc"}, - {file = "cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca"}, - {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d"}, - {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8"}, - {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd"}, - {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f"}, - {file = "cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc"}, - {file = "cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9"}, - {file = "cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b"}, - {file = "cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5"}, - {file = "cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210"}, - {file = "cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9"}, -] -markers = {main = "implementation_name == \"pypy\""} +groups = ["main", "dev", "floris"] +files = [ + {file = "cffi-2.1.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be"}, + {file = "cffi-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:42e2f76b9455f5a9a844f770bf3e200ed3da0e15f5df3db9c31fe80b04b3d004"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5a59cc1c4442bc3d5c703bf720b51138d0bfc173618807c9ee2490a7541dd3d9"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:9f8d177621de5cb38ee3e731eda45d421db093ec0739f46a5594babda7987a98"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:75f80557d1389eddbd0de2681f6a390a0c5338c31ddaa821381c203fc3fd50d9"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:194cffa889098ced9976c3fc6340305e43f6303657d298da55366907c05c22d6"}, + {file = "cffi-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5bb4e7ea95dcd6a014a6fef62e62467d67d8e582326443f3d68e71d6320a9fcf"}, + {file = "cffi-2.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3d22a20b1fb1632cc72c22f95f7b0d2961c3e1c235f245ba4c606c4771035659"}, + {file = "cffi-2.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1dea0e4d7d4f11f619fe8c1d76caf49e24405b4b5743c0e3be16a500ecd930c9"}, + {file = "cffi-2.1.1-cp310-cp310-win32.whl", hash = "sha256:7ce713ace7c0e4520535b42b77eaa742c16dab813978064913e5a3cf82973b41"}, + {file = "cffi-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:a48d62ab9d6f4f98c983223a547af44be6ca3691074c31cecced6facd3ba2dc1"}, + {file = "cffi-2.1.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12"}, + {file = "cffi-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632"}, + {file = "cffi-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd"}, + {file = "cffi-2.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a"}, + {file = "cffi-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa"}, + {file = "cffi-2.1.1-cp311-cp311-win32.whl", hash = "sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3"}, + {file = "cffi-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0"}, + {file = "cffi-2.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455"}, + {file = "cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0"}, + {file = "cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf"}, + {file = "cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517"}, + {file = "cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735"}, + {file = "cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e"}, + {file = "cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a"}, + {file = "cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80"}, + {file = "cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e"}, + {file = "cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c"}, + {file = "cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6"}, + {file = "cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2"}, + {file = "cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b"}, + {file = "cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7"}, + {file = "cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac"}, + {file = "cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d"}, + {file = "cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973"}, + {file = "cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c"}, + {file = "cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb"}, + {file = "cffi-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54"}, + {file = "cffi-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96"}, + {file = "cffi-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527"}, + {file = "cffi-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13"}, + {file = "cffi-2.1.1-cp314-cp314-win32.whl", hash = "sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c"}, + {file = "cffi-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48"}, + {file = "cffi-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836"}, + {file = "cffi-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3"}, + {file = "cffi-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676"}, + {file = "cffi-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e"}, + {file = "cffi-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f"}, + {file = "cffi-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4"}, + {file = "cffi-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e"}, + {file = "cffi-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5"}, + {file = "cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d"}, + {file = "cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b"}, + {file = "cffi-2.1.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4"}, + {file = "cffi-2.1.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399"}, + {file = "cffi-2.1.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688"}, + {file = "cffi-2.1.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7"}, + {file = "cffi-2.1.1-cp315-cp315-win32.whl", hash = "sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac"}, + {file = "cffi-2.1.1-cp315-cp315-win_amd64.whl", hash = "sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960"}, + {file = "cffi-2.1.1-cp315-cp315-win_arm64.whl", hash = "sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1"}, + {file = "cffi-2.1.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc"}, + {file = "cffi-2.1.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6"}, + {file = "cffi-2.1.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94"}, + {file = "cffi-2.1.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5"}, + {file = "cffi-2.1.1-cp315-cp315t-win32.whl", hash = "sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66"}, + {file = "cffi-2.1.1-cp315-cp315t-win_amd64.whl", hash = "sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3"}, + {file = "cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692"}, + {file = "cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be"}, +] +markers = {main = "implementation_name == \"pypy\"", floris = "implementation_name == \"pypy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -513,7 +513,7 @@ version = "1.6.5" description = "Time-handling functionality from netcdf4-python" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "cftime-1.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ad81e8cb0eb873b33c3d1e22c6168163fdc64daa8f7aeb4da8092f272575f4d"}, {file = "cftime-1.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12d95c6af852114a13301c5a61e41afdbd1542e72939c1083796f8418b9b8b0e"}, @@ -567,7 +567,7 @@ version = "3.4.9" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "charset_normalizer-3.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a"}, {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616"}, @@ -685,12 +685,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev", "examples"] +groups = ["main", "dev", "examples", "floris"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\"", examples = "platform_system == \"Windows\""} +markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\"", examples = "platform_system == \"Windows\"", floris = "platform_system == \"Windows\""} [[package]] name = "coloredlogs" @@ -698,7 +698,7 @@ version = "15.0.1" description = "Colored terminal output for Python's logging module" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, @@ -731,7 +731,7 @@ version = "1.3.2" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.10" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934"}, @@ -809,7 +809,7 @@ version = "1.3.3" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.11" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, @@ -902,7 +902,7 @@ version = "0.10.2" description = "Python Control Systems Library" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "control-0.10.2-py3-none-any.whl", hash = "sha256:8f7b5c58f5ccd761a6c070e3dedceca4c53c7a9cf105fcc22caba7a67f99025a"}, {file = "control-0.10.2.tar.gz", hash = "sha256:d0cf63f6cfb68a4c8e827c26c3744d129e9777fedc9a5d86ca4740548f23a98b"}, @@ -924,7 +924,7 @@ version = "0.12.1" description = "Composable style cycles" optional = false python-versions = ">=3.8" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] files = [ {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, @@ -992,7 +992,7 @@ version = "9.1.0" description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "deepdiff-9.1.0-py3-none-any.whl", hash = "sha256:80c0460e1993b04f6f0ca79abf25548b129fd218478c4ebb08f80560f5d10610"}, {file = "deepdiff-9.1.0.tar.gz", hash = "sha256:07e9e366fab4297755153c4eab795ad4ef3cbd0d51660e847f5751c6bd727687"}, @@ -1029,7 +1029,7 @@ version = "0.4.1" description = "serialize all of Python" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d"}, {file = "dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa"}, @@ -1045,7 +1045,7 @@ version = "2.0.0" description = "An implementation of lxml.xmlfile for the standard library" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"}, {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"}, @@ -1106,7 +1106,7 @@ version = "4.6.6" description = "A controls-oriented engineering wake model." optional = false python-versions = ">=3.10, <3.15" -groups = ["main"] +groups = ["main", "floris"] files = [] develop = false @@ -1130,7 +1130,7 @@ docs = ["bokeh (>=3.7,<4.0)", "jupyter-book (>=1.0,<2.0)", "ruamel.yaml (>=0.18. type = "git" url = "https://github.com/NatLabRockies/floris.git" reference = "dev/v5-beta" -resolved_reference = "1093f89913034481d90a1f691d3393df284f6584" +resolved_reference = "1f417ea73e27149fb5f67dec74c35e03e317f459" [[package]] name = "fonttools" @@ -1138,7 +1138,7 @@ version = "4.63.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.10" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] files = [ {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b"}, {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94"}, @@ -1297,7 +1297,7 @@ version = "10.0" description = "Human friendly output for text interfaces using Python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, @@ -1312,7 +1312,7 @@ version = "3.18" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.9" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2"}, {file = "idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848"}, @@ -1486,7 +1486,7 @@ version = "1.5.3" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713"}, {file = "joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3"}, @@ -1510,7 +1510,7 @@ version = "1.9.2" description = "Merge a series of JSON documents." optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "jsonmerge-1.9.2-py3-none-any.whl", hash = "sha256:cab93ee7763fb51a4a09bbdab2eacf499ffb208ab94247ae86acea3e0e823b05"}, {file = "jsonmerge-1.9.2.tar.gz", hash = "sha256:c43757e0180b0e19b7ae4c130ad42a07cc580c31912f61f4823e8eaf2fa394a3"}, @@ -1537,7 +1537,7 @@ version = "4.26.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.10" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, @@ -1568,7 +1568,7 @@ version = "2025.9.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, @@ -1599,14 +1599,14 @@ notebook = "*" [[package]] name = "jupyter-builder" -version = "1.2.0" +version = "1.2.2" description = "JupyterLab build tools" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jupyter_builder-1.2.0-py3-none-any.whl", hash = "sha256:c8a003714a118ebb590f79b459e1e384dee7dce9aebaa86ace045f5960997fe4"}, - {file = "jupyter_builder-1.2.0.tar.gz", hash = "sha256:e62ed4a7e224c73197dd76974754c93070c9f0451ca450a2c81126838b00f866"}, + {file = "jupyter_builder-1.2.2-py3-none-any.whl", hash = "sha256:6ebcd4c49daf5df6a18068a74a48010406700ed90a76c189fac43eaf85c60c63"}, + {file = "jupyter_builder-1.2.2.tar.gz", hash = "sha256:b6cea88f58e44b2c5eba96f28d2e0d16fd453d3ca6dc9c4492ff8a1f2e97f601"}, ] [package.dependencies] @@ -1615,7 +1615,7 @@ tomli = {version = "*", markers = "python_version < \"3.11\""} traitlets = "*" [package.extras] -dev = ["build", "hatch", "mypy", "pre-commit", "ruff (==0.15.20)"] +dev = ["build", "hatch", "mypy", "pre-commit", "ruff (==0.16.0)"] test = ["copier (>=9.3,<10)", "coverage[toml] (>=7.10.6)", "deptry", "jinja2-time", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-cov (>=7)"] [[package]] @@ -1789,14 +1789,14 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.6.2" +version = "4.6.3" description = "JupyterLab computational environment" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "jupyterlab-4.6.2-py3-none-any.whl", hash = "sha256:5964447036629adfcd3fc0969effc1da6f47d2cbd0a60b2c2eea7c31be0ec6a8"}, - {file = "jupyterlab-4.6.2.tar.gz", hash = "sha256:e18ce8b34f3de350e93cd5b2c4f3ae884cbe266eb76bf5d6825a4ed34c13bcff"}, + {file = "jupyterlab-4.6.3-py3-none-any.whl", hash = "sha256:0a1ebc6567186f1eabd99536e94df7ed9e96d1e7c5ddf3e4406ae16e88abacb7"}, + {file = "jupyterlab-4.6.3.tar.gz", hash = "sha256:2e3db6e3a12495ebd188276e985bf5ac502fbde3d1e8628819920210008de498"}, ] [package.dependencies] @@ -1878,7 +1878,7 @@ version = "1.5.0" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.10" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] files = [ {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374"}, {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd"}, @@ -2019,105 +2019,150 @@ regex = ["regex"] [[package]] name = "librt" -version = "0.13.0" +version = "0.15.0" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "librt-0.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:34e47058fcc69a313293d6dee94216a4f30c929ae6f2476e58c5ba635aa639d5"}, - {file = "librt-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dbdd5b6509d0c2a8fe72cf494c299a61dbd58142a90a4190664ae159e4a7b547"}, - {file = "librt-0.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e56ea4ee4df77585a6b5c138f6538680886024fa559f5b55bd14b12e98e67b2"}, - {file = "librt-0.13.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f1f9cc4d09a46d9cb3c2063ae100629d3f52a6517c3c08c2f4c9828261883929"}, - {file = "librt-0.13.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f125f5d46b20f89dc5587a55cc416b4ba2a5b2ffda36d048ee120e17598a653a"}, - {file = "librt-0.13.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2608d3b39f9e0b4a66a130d9150c615cba40a5090d25eeeaa225e0e46de8c0ac"}, - {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fd35e95ab5e45c3901d37110263c7db85a961110f5460588fe37f8c131f88a7"}, - {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5f31b0aa13c9b04370d4da6be1ab7779776b3a075cceb6747a39a4be85fe1e40"}, - {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0b795f5fc70fbbb787ceaf79bb3a0d627bcc33c53de51741755263ec406b775a"}, - {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36b306a623aaad96fe4b378692b54f9c0789fccd833b9851753d5fbf6138cfde"}, - {file = "librt-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a3762e75fcac8c9e4dacaaf438bffd9003e2ca2c531b756f3c0035deefa674c8"}, - {file = "librt-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:d63bae12a8aeb51380be3438e4dc4bd27354d0f8e19166b2f44e3e94d6f552dc"}, - {file = "librt-0.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1b5a7bbff495baedbd9b916c367d66854008f8f3b575908ded477c499dc60082"}, - {file = "librt-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34bc7938b9fdf14fe32a406c19c71faf894c5cee7e7474bd0be2f17200b82d14"}, - {file = "librt-0.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f40e56b61b41be5f7dec938cfeffd660668cf4b5e72c78e7bd671d66b7bc2c79"}, - {file = "librt-0.13.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:9c5d02b89de5acd0379a51ec44a89476fb03df6145442e1c8ecd6bee2f91b176"}, - {file = "librt-0.13.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7db9a3ff32ef5f7d1703d93831a3316cdf0b537de6a1cc03cc8fdd09b9194e89"}, - {file = "librt-0.13.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3dbb2a31882456cadc7053378e81ad7ed7693db4ac9f98ab5f81ef034aa8ec9f"}, - {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c6014e3c80f9c1fe268ef8b0e0ef113bac672cc032f2f93866e7ddad4f3e663d"}, - {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:091b60a4d2174fc1ec5c34cdc0b72efb6224753d76b7da61ebeab7a191aec8bd"}, - {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:66cb1138f384a191a6d75f986064841fcfdc0cea98f7bd9c9ab9b38049917588"}, - {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:17221a7569f8f292aa0014226e48aa25b8c2b08da18088cd230953d0ea0f9cd1"}, - {file = "librt-0.13.0-cp311-cp311-win32.whl", hash = "sha256:fc67741da44c6eaa90e01eafb586bbba9b51eb5b6ed381ee6f5ae72eb3316d21"}, - {file = "librt-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc99dfb62b23c9207c33d0be8a2e2af7a42e21e6ea388b380a0c948c7b88953b"}, - {file = "librt-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:40ccd13c252d3fe473ffc8a57be7565abc8b64cf1b108344c859d5164f7f3e0c"}, - {file = "librt-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30536798f4504c0fad0885b1d371b0539abb081e4570c9d7c641cb51141b49f0"}, - {file = "librt-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93d24ebb82aa4420b1409c389e7857bc35bd0b668007ac8172427d5c73cc8cc5"}, - {file = "librt-0.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb8a1adce42d8b75485a5d56a9623a50bcab995b6079f1dac59fc44034dd93d9"}, - {file = "librt-0.13.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0763ca2ab66058174f9dee426dc64f5e0a89c24a7df8d3fe3f1836c04e25de4b"}, - {file = "librt-0.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b222493da6e7b6199db9bd79502436cf5a27da3c1f7fa83c7e285444fc93fd03"}, - {file = "librt-0.13.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fadc63331f4388c3dc90090448f682a7e9feafc11481391c1e94f2f907a3976e"}, - {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:70d9c62a4cffd9f23396cd5ef93fc5d11b31596b9b7d6306074abe3d5fcf09bd"}, - {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66c0e7e6b02a155576df2c77ec933a70b72da726e248c494abf690923e624348"}, - {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ac04bcd3328eb91d99dfedf6a60d9c1f15d3434e6f6daf922f0420f7d90b85c7"}, - {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db327e7271e653c32040b85ae6188059c924b57d7e1e29f935523fa017cd4e82"}, - {file = "librt-0.13.0-cp312-cp312-win32.whl", hash = "sha256:860bd1d8ba48456ce08feaf8d343a8aaeb2fa086f2bcaa2a923fa3f7a3ff9aa3"}, - {file = "librt-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:e54a315caf843c8d77e388cadc56ea9ded569935ee2d2347d7ea94992e5aa6fa"}, - {file = "librt-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:c718e99a0992127af84385378460db624103b559ab260435abcfe77a4e4ed1c1"}, - {file = "librt-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a468951af16155824e88bdd8326ebe5bdb371f3ec0ac04642994b98201d914f3"}, - {file = "librt-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae01d8512cc17079e53425635327dbf3f7ff57a42c00dec348bf79791c56444c"}, - {file = "librt-0.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32c26893cd085c1efe83219e78d866da23fb20a066101b8f68210004361d224c"}, - {file = "librt-0.13.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5929da1981a46bcf4b28b1b9499905f0ff58e2419da402a048234e9783acbc4b"}, - {file = "librt-0.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b85d664d777bab6c0d709416cb42938251fda9e221b79e3a2215d85df5f4f9"}, - {file = "librt-0.13.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:531b2df3e9fe96b1fcf73a6d165921e4656be5f58d631d384ebce344298368db"}, - {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:109b84a9edf69ad89dc1f66358659e14a031baca95e3e5b0060bd903ede8efd6"}, - {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1304368a3e7ffc3e9db986796cc5326fdb5943a3567ecc137cff318e4240c0e7"}, - {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e4f9b472e7d308d94b62c801982065661158c6ed02790d6c7ddb4337cea0f9c1"}, - {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f836c37478f167a81200d8c8b2c920a22224564bed2c23d7aeec760965c367a"}, - {file = "librt-0.13.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:4000d961ff9598ac6ea603c6c836a5ed49bc205ade5fc378b998dfe1e2c36628"}, - {file = "librt-0.13.0-cp313-cp313-win32.whl", hash = "sha256:79e44cff71750d299d61a678e49995b0d5935a9cda238c2574daeca3ba536927"}, - {file = "librt-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:54dab44a847d5ad1acd05c8a83fe518ae685516ecf4d3f7cc6e3df2a66767650"}, - {file = "librt-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:d4cb6fbfdf874340ab5e51450753c0f817b6958a3621125ee695bbc3de866566"}, - {file = "librt-0.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:25218d94b1d2cbc0ba1d8a3f9dc9af578d9646e5ed16443a70cde1dfdcce6d71"}, - {file = "librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f26629539d4893c2957a16c41bb058e1e135c1f150f6a2e25ed047f64cf3f5c6"}, - {file = "librt-0.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4517d47b2b8af26975a406fba7d314de9696d864252e0257c6ea90238cfe27f"}, - {file = "librt-0.13.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f19e181de5b3a1148bb3420b8c4b0b0ea0fce6950099724ad151d6cea5acc180"}, - {file = "librt-0.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22034924f5b42d5a56371cf271771bfeaabf235a7a8b6264bef2d20013f786c6"}, - {file = "librt-0.13.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7897db4e95e22468bdda33d8e012ceacd0182abf001e6389d763f0def6286b9"}, - {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ce61b3746545029d4f5c17d6bd74b676254ad98433086c846ffb5e8fa73f007"}, - {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:46c330e82565962c761dbce7941be2cff7db674ee807455a8d0cadc5f9b759b0"}, - {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:375f5af8f99cbaa99dd293af986e3d57caabc9ba81a5d3f021603764854197a1"}, - {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9320d34c3376ae204b2cd176e8d4883a013934e0aef822f1aed9c536490c275d"}, - {file = "librt-0.13.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9af313c66157a69dc69ea0059a66961692250e0dc95af9c385a48ffb770a0d16"}, - {file = "librt-0.13.0-cp314-cp314-win32.whl", hash = "sha256:f2a7253458e34f33543551394ae4fe104b497ec2a65ac266074de64c1df82e37"}, - {file = "librt-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:a3dfe4edf10e8ed7e55b026a8bfc2c2a8704218b659cd4bffdf604fab966dc39"}, - {file = "librt-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:68a5faee4bba381cb93b5961f684a514cf0053cb92308ff9c792c2fea0b174c6"}, - {file = "librt-0.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a38fb81d8376dfa2f8963b265fec07637802b0d01e2a127c19c66cb070fb24f5"}, - {file = "librt-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d4c8d9bd5abce34b2e75edb3bf37ab0f34e49b1f915a40ae8468eb7c85bc5b46"}, - {file = "librt-0.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:387e2f1d27e89bffe0d3f520f0da0662c973fd607ca16c1808f8a5085419485e"}, - {file = "librt-0.13.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:4f6db193d2e5e0ed60359b9a5a682cd67205d0d3b1e459a867dd4b5c4e7eaa7a"}, - {file = "librt-0.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d38604854e8d22faadf683ec6c02bb0f886e2ba56ef981a1c36ee275f21ea22"}, - {file = "librt-0.13.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:371f7ce73026815dafd51c50ce38416e91428b28c4b2ec97cd39271164b0045c"}, - {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3aaedf52171bee90860704c560bc798fe83b76247df47568e0197e9b13c735a0"}, - {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:96bad8725a4f196a798366c25ce075d1f7543a4ec045ffc13e6a7ec095cdab04"}, - {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6bf6a559ffe4a93bbea6cf31ddf01a7fd9ba342ef51f27beb178e318b74acd61"}, - {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:301067672387902c55f94b51d5022304b36c966ea9fe1f21caab99a9bef487c9"}, - {file = "librt-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:5fdcf34f86de8fb66d7dc7589f96ba91c4aa46671200d400e6fd6f109a483f18"}, - {file = "librt-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:260c33e92263fa629b4f6d3c51967a1c2158fe6c33237aaa3ebeac586b085259"}, - {file = "librt-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2f281549a4c52ac7bb97997f14353f8bd0e53a34ca0dad1c905cfd0b4a58ae99"}, - {file = "librt-0.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f442e3954b1addc759faae22a7c9a3f1e16d7d1db3f484279dc27d62e06968fa"}, - {file = "librt-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e786428f291dd2d2f1cbfc0e0caa45a2e395fab0ad3e2c9314daa8873414390"}, - {file = "librt-0.13.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21b7ac084f701a9cdff6139745a6620579d65a9379ac2d9d50a86368b109e63c"}, - {file = "librt-0.13.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a6e556d6aba31c93dd97ce661d66614d2429c0a3923f9dc8f0af7e8df10223a4"}, - {file = "librt-0.13.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3657346f867469e962549435aa05fd15330b1d6a92829f8e27988e194382d005"}, - {file = "librt-0.13.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:791aa18a373b90da8ac3c44fc77544f33fdf53ae403acdce9b39f1c26b4a3b94"}, - {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d6fb0eaa108814581c4d3bfbd068c3fb6757812a81415008d1bae08267cca360"}, - {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a001519c315d5db40710f2665d32c4791f1d4779fc96a9423fd18d92c8b9ac7b"}, - {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:d9188caac26e47671b52836a5e2a49873a7fc11c673b0c122d22515f98bc14e1"}, - {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:05d96b80b95d3a2721b619f8982b8558848b04875bb4772fd54842b59f61dd97"}, - {file = "librt-0.13.0-cp39-cp39-win32.whl", hash = "sha256:c3cd253cf32fe4f4662960d6bf7d55cb8be0c31a5d644a4d48aeafebaff3409a"}, - {file = "librt-0.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:b15e26cc0fe622d0c67e98bee6ef6bc8f792e20ee3006aa12627a00463d9399f"}, - {file = "librt-0.13.0.tar.gz", hash = "sha256:1d2a610c14ac0d0750ee0a3ab8548e83155258387891caaca04def4bf7289781"}, + {file = "librt-0.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e1a49adf16a7c9d9646816c2946135527197b6fcf4347c7b8b761cf1bfbf4489"}, + {file = "librt-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81a398f45b45a59200e13cd5ad1ae1d3f44334de98b148331afe2cdfee701c52"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4eafbaff06b9563f8b1c850621ce51605de05208e09d4d71ce490bc972b7b9e8"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:b0411b4066db926b80258c60dcb0e6db4c9cee312eab45b7e8866b17ddf9ada1"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:febb1ce6cac545a54e6b769982824e955a700fdd9fbf3a08a3d82c990968b57d"}, + {file = "librt-0.15.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b230acc1c3bfe2d6f2627ba2b95dc92e58aa494600e9722d0e6ccbc931e59702"}, + {file = "librt-0.15.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6da110e5f314c19ab8478464d02ae18808ae73d522c15260fa4918acdcd64da9"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:eab9208b00ca55bf75983ec99f7bf13acc746a36102e98953addaad7f7ea1e1b"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6c013cd3a1721e69e14380ada97eaa4b7b0cdf1c6b96fa765d4ea47c875088db"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:567b1c430f8bd560e689421468278ac5941bab4a05303b5d95b6ae10db03f451"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:29c4cab9df457b19672c39be7f384ebb2bc925c4e2684b8780c222b43eb36389"}, + {file = "librt-0.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bccbd8e5b0bffb7106cf18eb1baa3d7194b1cebb3b4b1cdbd4bdb19382a6ee6c"}, + {file = "librt-0.15.0-cp310-cp310-win32.whl", hash = "sha256:8ae493ed5f659a7761c43d42f183db514536073ded9bcf671d2d1df47e29a07e"}, + {file = "librt-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:bc25fb356d0c7810bb49ff3df908ad1fda6995d660ab099ded69244ed7ab6053"}, + {file = "librt-0.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:823b92cf3c18ecd08afc70c42473888b41b6e8ef5046f3b82c05c154a2fa3d22"}, + {file = "librt-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70bc1b602cf59917e8f0c7a2cbc8bcc6fbc14d5486136b00707a79619121d63"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:814ff83a25b5fce8b9c80c4dd803153fb5c5599fc74db9e022466938368957ef"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:57f5eeb6ad4c180de583b1038e61fe5fbd9796bb69a8a1c1a0c7ddbec4c8c60f"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82909c8f7eb9952656b65d3147afde4cf8e6d5a991eebc86418b5e65843b0ab8"}, + {file = "librt-0.15.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f779070399f991400fc451719e0ea388eb7de313388bada2c127a35de05f798a"}, + {file = "librt-0.15.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bac89069bc496ebdf4f79ebb57bbd10d0b214c8454225deb672d91002bd17e18"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e0d00c708fb2f5822b152429b1ac80a58dbbbc3f6c232c4d13a3f7fcf2ea5b4c"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6c6624fe268625869485553dd7cc1daf30d22558215bb2a4ff16f67a9801a31a"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f56b397858a23dacf35ede366ed2212fdc03a6a57a1ad36468ad6e9dc5fac091"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4388184646efe2054911c5b00a1077d6d1ee86a95b7e8ba96dc7850a809f3f40"}, + {file = "librt-0.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97335f59082f9fe2ce6c2a9cc6433a0114bbb6cd4d5c09dd76c95c68b9f9a8b0"}, + {file = "librt-0.15.0-cp311-cp311-win32.whl", hash = "sha256:83380ffde38062a2e9bb55d83e74474f6614665528b98a6928720fc006dfffbb"}, + {file = "librt-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:f75720477ee05d509a310e856cacc8d909adc182f7b91193c207bcc26d7ee6db"}, + {file = "librt-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:256237037a3ab001ae8d9803b2d43562a4c3aa38739843694349e4d5ebb0fd56"}, + {file = "librt-0.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e87bc679f86a99aa3b26e3c78eeb821a247c9a28eae48eaafcc32c3bf4c3bb9e"}, + {file = "librt-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71599e011ac880e8e45d46047d714871894c7d4ab6f25626f8d4f89da21f368d"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c802434092b769b1d613ed2e13fac15fbfce1934a74bd10283b03c0fae231cd1"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5500eeae393a184d14e1f35645962c27129d20c81afa4069e6ef826ebc2b3aaa"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6ecfc32dfb46fb7b565bcd6abf9412acf978775a998273d22888a6d7953730dd"}, + {file = "librt-0.15.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cc46cfd15022e35084355478c9ac809d90b1152222706ac9a7655ec21df6fa"}, + {file = "librt-0.15.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d5f51401d102c885b9ca509e62c79b1dbff286e1b9b047fde6f763780789356d"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cc30523e3f1a23fb7511cc659834a0d01a1042bb9de359bc1c131cc4ec6c9656"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:59fe030d8ae4a57e3fb7756bf35a858de74e04066fc8555c53d0af979132af81"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a6526a2a956bbb1e4ae3568c82e650fc99119c66bb011ea60715744955a2b4d"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:85ea21ec6730194d67156b0e0b5430ccb1d61f8b8b907e39b37f9812b74a13f0"}, + {file = "librt-0.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1e47b8ba865d7ede071a91a7163073bbaeb72541f1ef8a07d512c45c7b5007f2"}, + {file = "librt-0.15.0-cp312-cp312-win32.whl", hash = "sha256:a5207ec414d1c4a2a7231b2086970dc036f94293cdf338190984958a013a42f1"}, + {file = "librt-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:73b30cfa976659b3917c8f6153bdb0591c6a9ec6583599fd24a689b690622022"}, + {file = "librt-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:a54cf9e0ef47b96af580849db5471142200568ce1e02cbf416addab551369570"}, + {file = "librt-0.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:db13ca398005abcbe538deda87b686d9bd08b7001cf40c4c06b444960ae10a26"}, + {file = "librt-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa1f1995789dca3698bc550aaceb09a51bd5df0a057ff84ff15296cd1975b801"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55456ea87d8df21808446d03817be2f65e20391c1c615d9187440dff28cd08dc"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5a86a5a08c2235316bdb359d5dbb6ce0abfca7fac06363103e2c5af571d92f95"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e56b6a368529bed262da40ce13f8fef590db0479819cca84f16a1f01ac356d0b"}, + {file = "librt-0.15.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:234d8d394721fa0d786af15ebf1f3fb7f3ed82fd1cd0cde45c2f247b5d4281d2"}, + {file = "librt-0.15.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d8363d7accb0286ac3a0e633f396e93800dafb8150494505daf9515bbda591f3"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0f0ee3644d951f31055ad07d77d92520e84505dd7a432cc4cd501dd70ee06785"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cfd1a81a648806e6a7717be4cc4d1bb392fa229752bf8444ba365e381e984d6"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a6cd22c9da0d866558e46a041f1cc0c2bbb26b61b137b2347fa834c332e1d101"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:6d5225ef8801e4ea5e482fa9b5dfb891dd9ef6f6d870f1f25d449ca2c70ac218"}, + {file = "librt-0.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d28a05796b99f749bf8794f17ba9ba1612d0076b802e9cfc62c554634e9ce3b"}, + {file = "librt-0.15.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:2067ff438048cead9d223ca5675bae2a25e520a7c3e6c1498bf9c6892d22caab"}, + {file = "librt-0.15.0-cp313-cp313-win32.whl", hash = "sha256:1cd3b721f24c206398b9e26da3c3a9c011e6e89d06f318ba8ebefc30f1003890"}, + {file = "librt-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:f395a4a9a03ac062dbe9a9f82e0c720502e590a38feee6a757bc82e9c63afbd8"}, + {file = "librt-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:0a15cb554761247d84a3ec0cbdf4078d70725384f0e4662c0fa3b26266eb60ad"}, + {file = "librt-0.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f5de7feedc56337a088eb15cd9fafa9938367362221d8cc62c642b7f94821993"}, + {file = "librt-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c0eb900c0e91f4aebe680845242e614f1864edfd44106380d0752ac29522bf8"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e8c9a650a188e38bac005048cbe6342e81407782944d01934540ab75e417df21"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:92bfed8deec93df30286b9fe9e3b1dd17329cc076a192b4ee5ec223841d54953"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec4b19788f835711a2072f9dbe6b03b3bf32ed1f0fb30cf399bdd59d9f0c33fa"}, + {file = "librt-0.15.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4c7bacb70930f3d0a56f4ecf1be474a1f0d941b01dd73b756f3c256d42cb879"}, + {file = "librt-0.15.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3e79f05e4a08b4d880342673312bbc895b56df7765605796f15902eb5367d3ae"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a417149c0cba4d50b61e992e5a15e69eaf96746609b461cc4ed168aeef6b79dd"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:da7a94d6a3411f579d72aa3e3bc5fbca7ed4549f3dbd7e5de3aa567333374285"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:856f743ae607f2c1380eccb566c0038a9fb3eabf0fc2be2704d76d9f73557239"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:779a6e7c894737e5983e7790a9c78c4000c30e23c9aada08081bdbea53b0fa60"}, + {file = "librt-0.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:96bb17dbe8bab3c0954fbebfc69ed395599de75b6bbc35e3270a878e15d4dd65"}, + {file = "librt-0.15.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:7220697efaa6e5348fc3d18ee7f8563d4bfecd9872b37ffb915bfc1d08840622"}, + {file = "librt-0.15.0-cp314-cp314-win32.whl", hash = "sha256:f54598964d357b1c5ab77cf5d92f21e598fe0e23cdbe9618480807f81b4eba15"}, + {file = "librt-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ff5893a2c23d886aa9ce786de5ac6ddc74aeeaf90743682b74d920e117d2e28"}, + {file = "librt-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:3722a099730704c9a3d70c879fc0f51daec25fe5f1555672d97bc595abeafb95"}, + {file = "librt-0.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:38c0c7d4b6fc06c3324b3f9162c8391bfc4fd9dde53afe1033ce7edb48d5a714"}, + {file = "librt-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8b2fdd7ead3c995c37940a790690660d0ca006c302db26cc51933f6766866fc3"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fde98cf1fc4bac144ce23c2c4c017b924ba714509ea9334977b0b27050c837d"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:e3b461183c5fa7681b48560f91515f53a953122fb30c71e07abc67d7ddf58c38"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4bbcc257e3babea20a91715c361b24554ec4e8f51aa578568afc230799fe1a19"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b845b8d48088fad0cadc84be4b8fda63203be7e9237b71015b3925443c1f35ab"}, + {file = "librt-0.15.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b30e600e8f337b9bd7f39b86d9fdfedc73cc46e3d0f745931a23a234220bb7e2"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:64b0c8c35aa4c4ed79896359f3e0b285cbe4e610042106500da4811c322cc108"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0da0d94cb802f32a0524653e7201f2cef72d5f700a5407678f5290483d4fcd08"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4a6369168d371207339b1e50d4532b06a7121586141f82599505a3f315751d47"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c434e072557ade9cbc642d052c89d031efe47d5c9614523619d0d74a02378e81"}, + {file = "librt-0.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7eec6a42018bc1d45763b1c162d3d2bf7c3b9a1b0ed30d3e91dcba390efefcc"}, + {file = "librt-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:6912fa5e635d74529ac7cdb1bdf6ca3af4453da8d1edbe0110ee1cb4ad407ebf"}, + {file = "librt-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8e11699ed745931c395acd3621b07062e0f840efa6935aad87a64ed0995f0915"}, + {file = "librt-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5d2a91724463bfed4f573cd7a9fdc856d2e230d0c0e5a61416a93481dccd8605"}, + {file = "librt-0.15.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:8443e38dcfcfdbcf5add5118c623efd788d65ac2e25756d6251a54a06a4d0aca"}, + {file = "librt-0.15.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:6d15a29033c57490cfe2069097c6fc4049e4e65ffbb749be7dc453b7c4c68965"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2c05c729b589e734c09578bf5964be48a911765484840d017bbc84f49d4c4ad"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:fa60887537e1d0cd2d9982269d33a709bf54b195cd2b9364fc0a758022af5bd9"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d8bc24219b24c0af375718942ab75e3544b2763085f40f965be4326734ae8328"}, + {file = "librt-0.15.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86a21a7bd3fe3a419512ef424cc1c020f6771d0b29cfddff36d1635a855e63f0"}, + {file = "librt-0.15.0-cp315-cp315-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dbab647e88d90b3167b91efe7091e248653688ed4337e4f90907a722c7361bb9"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:d8edcf6f550e918dca779c069b9e156385c60b406f99fc7641f32c52f7193659"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:8b62076030baa2d8b1501a46bf0e19c27a489aa90671c55665bff7887f7660b0"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:d00d20d1818e82a07a0ee0aa89a98b17ed7916b92441090b683719cb20a59b6d"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:4e6ee93fc3cf848dcbf0cce2eca73d8e7dcd0cc2b6df3a529d57750b30a4c55c"}, + {file = "librt-0.15.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:32896a0af72508ea979e0acb4e4c04cbeeae04938167950d535c83c45597167d"}, + {file = "librt-0.15.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:ec3ba415afaf951f6951b1dd16d3c8e4f540065fc382d7e70b823a79567ca374"}, + {file = "librt-0.15.0-cp315-cp315-win32.whl", hash = "sha256:d2813ba2503764f0450680c533d13df7cff9b49df1411062eded5f67db4195b9"}, + {file = "librt-0.15.0-cp315-cp315-win_amd64.whl", hash = "sha256:b87d67e33afaf265262f2a66db578284b88ee2e6fcd224579cb5c15518677ad8"}, + {file = "librt-0.15.0-cp315-cp315-win_arm64.whl", hash = "sha256:713bd7df21170b982e729e46870f31d6b437bd1a9b4648cffb529bd3c2ec5c4b"}, + {file = "librt-0.15.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:3de789c82752730f94782a5ee518baf9c05edf85733aeaf73bb6e518755cdf54"}, + {file = "librt-0.15.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:e0b5deec9a8664eb722c797241970fd4aa1894d25fda36a1ddac0f7407606bd6"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5563302a8359bc2295bb7084d1a8ed1519df96afb30eb2aa4e0bff7b54228988"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:22d6263b9d39d7bbb286fa791945646e3218f1be2d693e36fb630f1d0e59cd13"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39ffd14646190c454f0d86e0d256b33f00a87a26ab410e619773b841d0e41416"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47318cd3a61401452de11282242937e3e057c4fd3dbaf601e269d0928a06c0a"}, + {file = "librt-0.15.0-cp315-cp315t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a56a1d4f859a82ca5b99fc4b82c9b027b15e3c455c5cd99e7d0719f27bb20b6c"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:077471b3182db4e17c36ae91555f36a4d2c00080b267f749bcad34a478a9a302"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:411ca4d1b905b860ceba7570dd6717a71dedaddcc4b0f77ece710aa41ee11f8d"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:1256589e0b0adb31751d685a68bce29d73407ddf4ef05d4188f49d5dcf9566d9"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:f42b74a53e5f26a0ba0007411a7455b66c67ce4022a39cc1f56fc4efd65bcbab"}, + {file = "librt-0.15.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:291bf73caf78b9e88d6fae9bfd693207ff7d832e2fdbe2cf8e746bc13f5f892b"}, + {file = "librt-0.15.0-cp315-cp315t-win32.whl", hash = "sha256:c16d15ee371643ab48dc8248a3e680ebbeca573a13af2c3dd0c985b142d77162"}, + {file = "librt-0.15.0-cp315-cp315t-win_amd64.whl", hash = "sha256:dbd605739f228912dc49027cb764456b9757750bdc2b6b7773164db7096c6fd1"}, + {file = "librt-0.15.0-cp315-cp315t-win_arm64.whl", hash = "sha256:84d244b00604d17df3fc7736c327892d6bba66181254aa4087be807b6c342bdc"}, + {file = "librt-0.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0e2d0c0acf5b0ada7d045912b7cf787c21315c95b38b1fa939ef72d45d366b3d"}, + {file = "librt-0.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9ca190fe9edc0eb08eec558a509a16d28d91c35667b8f043cba40ed5e77a959"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80811e1c42386ea95c6fb30571d3250ad43d7863f883f787f70517f441150e59"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:88c2a17815c266e6d8180204ff62cb739ab869ada4a746d4c505331526ac58f1"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a5fa8f1f916988d0bf1afea005bda37f56ac41a18016e813ccf0097a8d460ca4"}, + {file = "librt-0.15.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:355e3a4c725225a14262004fc1872a552b9d3634b4f791a0dfc80804aafbfd55"}, + {file = "librt-0.15.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc1ed11c4ad0b91af24def2050f2840ea4567828e3dd058fbe608d982f6e5465"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1f4ef2e71db33df4309167ed7f1520c4fae5e611226e159fa9cf33f93e6ddb3d"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1a1a8cd430c7dd0c083f455cb1b328d7fc682b05c31b940906f7845bdff80881"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:04d5387b908676c0b8d5d2f5fb58373b4ea382d81f7a6f0fab8ea2a462bb4738"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:1172c6ad2a88b646e7fe3b480e3fac4ab4418b3443fd8a4061fdd531e0622fc7"}, + {file = "librt-0.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:52e8db01f603f5da0ca30987479acff98769382efc8e142fa3962395dcf3ffdb"}, + {file = "librt-0.15.0-cp39-cp39-win32.whl", hash = "sha256:e4c911f15a1652ca94ae9f1abd92e74cbb1b3597d2d92fdd556202f94e8cd455"}, + {file = "librt-0.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:68242379c9b65a582b6e97318a1e9fbd6d445e58954f2d437991c4804ab11578"}, + {file = "librt-0.15.0.tar.gz", hash = "sha256:4e66cbe84437497d951b799d3e1551291b6fb3d643820a7014b3655d57a59162"}, ] [[package]] @@ -2225,7 +2270,7 @@ version = "0.2.5" description = "Agent based processs modeling." optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "marmot-agents-0.2.5.tar.gz", hash = "sha256:d0038c28928681b74352397a357f290da00c86a10c9626219b3ae36899faa915"}, {file = "marmot_agents-0.2.5-py3-none-any.whl", hash = "sha256:f7678a830593222436396163fb0788d9d113bf84afb956b8854aad465830c2a6"}, @@ -2240,7 +2285,7 @@ version = "3.10.9" description = "Python plotting package" optional = false python-versions = ">=3.10" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "matplotlib-3.10.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77210dce9cb8153dffc967efaae990543392563d5a376d4dd8539bebcb0ed217"}, @@ -2320,7 +2365,7 @@ version = "3.11.1" description = "Python plotting package" optional = false python-versions = ">=3.11" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "matplotlib-3.11.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b7cf158e7add54a8d51ac9b5a84abd6d4e13ed4951b4f25f1c5139f41c2addb2"}, @@ -2421,7 +2466,7 @@ version = "1.3.0" description = "A design-oriented mooring system library for Python" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "moorpy-1.3.0-py3-none-any.whl", hash = "sha256:2a6bf0f9db32fd49624471aeb152925ede383c0414db853c47069d5b3cd55b12"}, {file = "moorpy-1.3.0.tar.gz", hash = "sha256:ccef5e65a8a0f65be48e0fc39275918c318390937bf426c26a96d5fda0692256"}, @@ -2444,7 +2489,7 @@ version = "0.70.19" description = "better multiprocessing and multithreading in Python" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "multiprocess-0.70.19-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:02e5c35d7d6cd2bdc89c1858867f7bde4012837411023a4696c148c1bdd7c80e"}, {file = "multiprocess-0.70.19-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:79576c02d1207ec405b00cabf2c643c36070800cca433860e14539df7818b2aa"}, @@ -2610,14 +2655,14 @@ webpdf = ["playwright"] [[package]] name = "nbformat" -version = "5.10.4" +version = "5.11.0" description = "The Jupyter Notebook format" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}, - {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}, + {file = "nbformat-5.11.0-py3-none-any.whl", hash = "sha256:f70a17f591a9ccd1c601d5e61a4b20972703926df0ba42458ce14bf575766bb6"}, + {file = "nbformat-5.11.0.tar.gz", hash = "sha256:7dbaed4a69cae28c2b4d44ab7430a6af4544fb89455023f6f21550be757b60c8"}, ] [package.dependencies] @@ -2627,8 +2672,8 @@ jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" traitlets = ">=5.1" [package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["pep440", "pre-commit", "pytest", "testpath"] +docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["packaging", "pre-commit", "pytest", "testpath"] [[package]] name = "nest-asyncio" @@ -2648,7 +2693,7 @@ version = "1.7.3" description = "Provides an object-oriented python interface to the netCDF version 4 library" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.11\" and platform_system == \"Windows\" and platform_machine == \"ARM64\"" files = [ {file = "netcdf4-1.7.3-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:db761afd3a6b9482df018c4783e0bdf99141a41db1f14c68c89986effb182d57"}, @@ -2679,7 +2724,7 @@ version = "1.7.4" description = "Provides an object-oriented python interface to the netCDF version 4 library" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] markers = "platform_system != \"Windows\" or platform_machine != \"ARM64\" or python_version >= \"3.11\"" files = [ {file = "netcdf4-1.7.4-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:b1c1a7ea3678db76bf33d14f7e202385d634db38c5e70d8cf4895971023eebb9"}, @@ -2724,7 +2769,7 @@ version = "3.4.2" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, @@ -2745,7 +2790,7 @@ version = "3.6" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version == \"3.14\"" files = [ {file = "networkx-3.6-py3-none-any.whl", hash = "sha256:cdb395b105806062473d3be36458d8f1459a4e4b98e236a66c3a48996e07684f"}, @@ -2769,7 +2814,7 @@ version = "3.6.1" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = "!=3.14.1,>=3.11" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.14\" and python_version >= \"3.11\"" files = [ {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, @@ -2789,20 +2834,20 @@ test-extras = ["pytest-mpl", "pytest-randomly"] [[package]] name = "notebook" -version = "7.6.1" +version = "7.6.2" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "notebook-7.6.1-py3-none-any.whl", hash = "sha256:6ea1e4c926f0dc490444ddcc335797a3dacda470a805d01031872fb119988ba2"}, - {file = "notebook-7.6.1.tar.gz", hash = "sha256:0b45fd1010668dd4808c40914d957706dbf044a677d28764dc881b74dfcede82"}, + {file = "notebook-7.6.2-py3-none-any.whl", hash = "sha256:5fe9e09c335cb4b7de21627b860f77210e70e54b1fb1276ad942a4a7e1d858d3"}, + {file = "notebook-7.6.2.tar.gz", hash = "sha256:cc02b5f0bb972160cccfe44ad8a1a202036206ba3439469c514f03aefa9ae807"}, ] [package.dependencies] jupyter-builder = ">=1.0.2,<2" jupyter-server = ">=2.19.0,<3" -jupyterlab = ">=4.6.2,<4.7" +jupyterlab = ">=4.6.3,<4.7" jupyterlab-server = ">=2.28.0,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" @@ -2836,7 +2881,7 @@ version = "2.14.1" description = "Fast numerical expression evaluator for NumPy" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "numexpr-2.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0fab3fd06a04f6b86102552b26aa5d85e20ac7d8296c15764c726eeabae6cc8"}, @@ -2907,7 +2952,7 @@ version = "2.14.2" description = "Fast numerical expression evaluator for NumPy" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "numexpr-2.14.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2aa65ddc2243f19c6915f34ee0978b4a2df20f297230a793c4ee6d55f3472599"}, @@ -2967,7 +3012,7 @@ version = "2.2.6" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}, @@ -3033,7 +3078,7 @@ version = "2.4.6" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] markers = "python_version == \"3.11\"" files = [ {file = "numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4"}, @@ -3112,57 +3157,79 @@ files = [ [[package]] name = "numpy" -version = "2.5.1" +version = "2.5.2" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.12" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] markers = "python_version >= \"3.12\"" files = [ - {file = "numpy-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c889b56fe48b1018f764b0eec8df59ab654e9148aa91faa12596043500de277"}, - {file = "numpy-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab451b59c5643c570974c43aef780703ef1d3b4965d2be07afd530615a9358d1"}, - {file = "numpy-2.5.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:78798bd5b9ad744056af8efa90e3b9ddaa53272a0848a483084a1cc0a13b2dc0"}, - {file = "numpy-2.5.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2ae0ca40bcb22d6ba59c1dfd5446f49940b0f2d821fde133f10dda11f816b84e"}, - {file = "numpy-2.5.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61ac47e772e6b8ea489e1d2f441a34c5c3ac17327e7ce294cbdf535795ad4e75"}, - {file = "numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59fda5e192b570217ec2580c96f00e9a7e12ef6866a900eb089b62c1a32545ca"}, - {file = "numpy-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f7119ebff1a9829e9f431a4f9d28e703023bb6b9fe7c8f724467dbfc27c94ab3"}, - {file = "numpy-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e824c2acf8862052246be5a44c15da1777940c60d010dd2aab897824d9c430f9"}, - {file = "numpy-2.5.1-cp312-cp312-win32.whl", hash = "sha256:08d60c810432eb83360958dea0999ac4cfb94531ea8efcbf0b7f277c2068aeb2"}, - {file = "numpy-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7d60026c0bdb1380e83bfa7a0419c4577ee4b9a08880afcb6dadeb74c649fa2"}, - {file = "numpy-2.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:17a25e09640602e10bc8de0e6fa2b3fd68eedd84ba6d7842dc8f32f9ab87bd0b"}, - {file = "numpy-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0bfebd8695f9863592fe744be833a258120b14a9f39da255e8aa8fade2c0ddd1"}, - {file = "numpy-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30b44a6b53a7ae63c54c089a8726e5563ed302716c5b7ccc85afade40b0e7ff6"}, - {file = "numpy-2.5.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:6165343f81b56ef8f514f396989e529b61d9dc709b99421b07e9f3e698e2287d"}, - {file = "numpy-2.5.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4939237038ada79308dda3204ac6462df056b5672b2e25db1149cf873668b3e1"}, - {file = "numpy-2.5.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c6759f538fb912fc46de0a6b1758ccf7b57bc7c7ebebc23974fdac3de8db0cd"}, - {file = "numpy-2.5.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9726558e8db4a5bf7929a70ae50f63abda4daf0efe810e3bfbab95976f75fc1a"}, - {file = "numpy-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3935f3b419b244a02732676fa5317a9193cc596a4c0646db07e5b421229ac9f7"}, - {file = "numpy-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc932a65ded7ce9013d120845a2514dcccb1a67bfc8deb8d37633762951904a6"}, - {file = "numpy-2.5.1-cp313-cp313-win32.whl", hash = "sha256:4b4ff1608417eb7a59da7b967bbb798cacfe071d2caf526a24281cd562072ed9"}, - {file = "numpy-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:6c3fe51bc6a16453d452997053454f309e8e0ed7b42d6b361ce4ac8c32913d74"}, - {file = "numpy-2.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f7feb014281029e628ba2d5a007407443b06e418b6fe451d1e2adcbc8eba0107"}, - {file = "numpy-2.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7c786fe9a5bbe360022e584c5a34cf6b54265c71bd7ec8ac3d8fec38968071f8"}, - {file = "numpy-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32985c896d897419ef8da6917872d80b78ad0ea26d85b23245c7366ffde76d75"}, - {file = "numpy-2.5.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:efd736408cc97c79b9e6917338dfc8f06013b2274f992e96b1d9a81a71e2a2c2"}, - {file = "numpy-2.5.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ab84dc6b074fa881cae55bea94cc4f68e285181ba7f32497bf7dee6b1496165b"}, - {file = "numpy-2.5.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caf3e317d33d60c37986b452613f4ab51246d0691350c03d0cb4a898627f4a95"}, - {file = "numpy-2.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54ad769f17bc2d833b620851989f62054fb9ab93c969d9e1dc3c8e3d56beea21"}, - {file = "numpy-2.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c12afb53450fa976d4c681c50a7423729a4c51c0465ed9f32b8a9cabbc472373"}, - {file = "numpy-2.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c11c405efc5ff6816d5983c96cdfa215bab3428961243af3ff59b228490438"}, - {file = "numpy-2.5.1-cp314-cp314-win32.whl", hash = "sha256:f2479a47f8d5932d1718168a681ad6e536a9df484c83cfcf9de365e164537ace"}, - {file = "numpy-2.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:24d0eb82c0541d3415a33425db64ae439dffccd7b4dbcb30e7c35120205c506a"}, - {file = "numpy-2.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:5a4c988b38d261deeeaad9954e3deb091ad905c94e8bb6708654ef1d97f286b0"}, - {file = "numpy-2.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a33276be12fa045805f477f22482088b66bb758ffbe89a9d21457de863a32e22"}, - {file = "numpy-2.5.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f089d7b00756190aacf1f5d34bdf38c3c430ac82b4f868f8cede73380460fce7"}, - {file = "numpy-2.5.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:09e9bfd8d2cf479c7d174804fb3811c53a8e9f20a37444008606b57d6b7a826d"}, - {file = "numpy-2.5.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e68d8dd1e7eba712948f2053a29ec86917bc70ba1358df869d9f06649ef9cf09"}, - {file = "numpy-2.5.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99d5095fa265a0c4152e7bb12759e14381ef5496152f1ce58f44bdf55c44beb4"}, - {file = "numpy-2.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ab87a91b3cc3382b8956095bd8f95e00cf679bb81554339be1a2ba404a1473c1"}, - {file = "numpy-2.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:224ca51130ef7da85bea2191625181cb4f337f9cb64b471f10c1a12aa8b60077"}, - {file = "numpy-2.5.1-cp314-cp314t-win32.whl", hash = "sha256:6eab239876581b2b3c5a242281b6007bbdbcd1c7085d7709bb57c5929b11e6bf"}, - {file = "numpy-2.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:83ce9c80d5b521b0d77ddcbe5447c218d247929b6cc056ca5351342accfff0af"}, - {file = "numpy-2.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:5a6db61f9aaa57e369905c67d852045d3c4f7126405b29d09b19dec118e9c9cb"}, - {file = "numpy-2.5.1.tar.gz", hash = "sha256:a48a113e6afea91f5608793bafa7ef2ad481fefbda87ec5069f483de61cb9fa3"}, + {file = "numpy-2.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:14e373cfc6387177e8409dac3c7159be8eb05cd77096cd7c950268b86f62831c"}, + {file = "numpy-2.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bbd96c833ecc8cc069ce518078fc8c60cb9cbfb0fea5b7a803ad65035596d03"}, + {file = "numpy-2.5.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:6e8172ddfcf5cf74b811d372b570b83c60bd2de87a6fbfbebdadb4a9bd9c6cbb"}, + {file = "numpy-2.5.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:65f188481f1669e26f62b701e8205d19e460fa4a9b52a1414ba382330e4a3414"}, + {file = "numpy-2.5.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ee9c4eeb8454b3660a8b53493563c3e121c2fc94fbd72b848ef814ed7b676a9"}, + {file = "numpy-2.5.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3cdec01fa790a186d430433fdd4d4ffb70eed6f0eeb4bf05c8dbe2dce0a9bcb8"}, + {file = "numpy-2.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7999d4ddb0c4025018373fd787510d46e04c769467af22869707b3c1cfd459ab"}, + {file = "numpy-2.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c1f017dc0875c9209d219f97feceb7d54c2661bb243deb4114478e1295808af7"}, + {file = "numpy-2.5.2-cp312-cp312-win32.whl", hash = "sha256:d6a48072864e3324e194a8fbb3c657bcc5b5c869dbc64c9537b1d5c862572c0a"}, + {file = "numpy-2.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:28ac63476ec7651484215ee7fa15a1f78b57c14621f01e392afe17b9a1390ce4"}, + {file = "numpy-2.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:27650bb0e7140fa3d37b9923b4803645e0b125d190f326eecfd3f4dad8e8ade1"}, + {file = "numpy-2.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8e4cb9a754c8a0c62eaa88273a5fba3391f4a610d1dee893c0755da31c083f15"}, + {file = "numpy-2.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:52c808f96484f5571a5cc863775ce50247c17dfb3b0361f8ed6b4b0456f80080"}, + {file = "numpy-2.5.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:29d81e97f668489cba8ebfd796b9bdd453525d35dd9e162e2daec94bf3fc7740"}, + {file = "numpy-2.5.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:afb3f0632d6b2e3ba04dbce8d1e48d321b369138b73830b5ca371a0e8d479d56"}, + {file = "numpy-2.5.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0aadf13b60048d501e05fa699efaf7734e2494f3498a4c2a5521d822640324f3"}, + {file = "numpy-2.5.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29b86ff8a6cc556b47ec6b64b194815cc80e6bf5eedcc6cddfd65318cb0b4eee"}, + {file = "numpy-2.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6950c4b7dd562453090548ba7f5da7e59f57f85663f15d5dcc60e249192f7e59"}, + {file = "numpy-2.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9727f472d2f3888053b8a75ab0cb94745a9de224bb5846dbadc0092101bc71d"}, + {file = "numpy-2.5.2-cp313-cp313-win32.whl", hash = "sha256:4f9744f9fbdcea0bc552e8f19e1f141f811a3f9bc2be2cc6e86d982cab23e3f4"}, + {file = "numpy-2.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:85aaccb24182c25df891ad0ec333585967e115269d5f1b17f2c9ae005bc96657"}, + {file = "numpy-2.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:bd68ece1553d2023c09a4226d9e41c586ad2d20594d1a456186c33513d2cb3f2"}, + {file = "numpy-2.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d787cf769c3baeb5f6235e778edb52c08dfa923789b5958f28e6450f96107cb1"}, + {file = "numpy-2.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:24b9dc2e3d84aa58523798805194e23e736f3f6ce2d1a5b92583ae734e6dbda8"}, + {file = "numpy-2.5.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:9e9413326d726c2545bfa65d2c0876871e8d8386e77f992c1d426e180bbd4323"}, + {file = "numpy-2.5.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:60e902ac295855348a5ca2ea4c89108989a9f5fddfad3dfc0a8f36b10358567e"}, + {file = "numpy-2.5.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50e500dc868e9313530ce12ba470fe50ff3afe3d62993ed6eff652dacd555b65"}, + {file = "numpy-2.5.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318b9a4c845dbea06708a29c84ee429cc3065048db34cdb799047643492050ee"}, + {file = "numpy-2.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:34c319e2963be042673fb46570501b2f06c41924e17e3563d58646b4380dfb68"}, + {file = "numpy-2.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f06571a052127dc1b4e8b83029b4d1b20daa2b64a31cdd181fc6bc774e9000eb"}, + {file = "numpy-2.5.2-cp314-cp314-win32.whl", hash = "sha256:2cc779226e476d1e1f08c74068c419e60f41a9e0e069c92f6671d31d5c985e98"}, + {file = "numpy-2.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:7587f53dfbd5edc0f7b87c6217b4c6d2d1f2ef9c3da70bc1315e7db5f8d7ec9d"}, + {file = "numpy-2.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:3e4c367352d3747784248a227fbec218e193b56f7e6692e3b64fc805478ecfdf"}, + {file = "numpy-2.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b879fb674276e331513fb136b78dbc6bd3c848309e0d841cfd63be3896c4cfc1"}, + {file = "numpy-2.5.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f"}, + {file = "numpy-2.5.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:3a2f061cebd9e3d23bdcfaaded5e2293a4c6a5b60fa42df85d410a725ce621bf"}, + {file = "numpy-2.5.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6df895598c0edcb41030126c89e0f353b07d93238116143b7405e937359736c4"}, + {file = "numpy-2.5.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ab3d4a901f844ea836c3e80bf463c6a27d7f3c14e8e292fcf28d348b25b9bce"}, + {file = "numpy-2.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:cebc2d6dbb605a7703d59751dea4bd6b0ab127a5a4338a6f432df1936fef8b26"}, + {file = "numpy-2.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eaca7ff36f0f52e2111ec71f169d8fd3e889e7ddc0d2592e0d703fd8d3ce8fac"}, + {file = "numpy-2.5.2-cp314-cp314t-win32.whl", hash = "sha256:ddf47472af2e4280d79bac82304f5e80150211f1b9e614b760061d5fdfbb6eba"}, + {file = "numpy-2.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:44ef9675d908e65f9953063837c3277730f3f4437615a4cdab67b366cabaf884"}, + {file = "numpy-2.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:eaa088384c46f519dacb93b7ec483a6d6b19a4a2085ae4f25ab9b1c43d387d1e"}, + {file = "numpy-2.5.2-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f"}, + {file = "numpy-2.5.2-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:50a68f4bacd8a2b33d8da3d2269d0d78500f86ea582e4786dc10f5ef2c2c6842"}, + {file = "numpy-2.5.2-cp315-cp315-macosx_14_0_arm64.whl", hash = "sha256:e79aba74ffaf5f78a050d777c184cddf8fdffabab38acf5f3ef1fecbc17895d6"}, + {file = "numpy-2.5.2-cp315-cp315-macosx_14_0_x86_64.whl", hash = "sha256:9a0731745a72a184490a582fb4af2533512bd071ace67785b5fdffc0ae58dce8"}, + {file = "numpy-2.5.2-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4ec954036759bcee3aa484f8603bd9c14f3e776293b85578b8734c2d72777c69"}, + {file = "numpy-2.5.2-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc649493697006bc90614a5f0bbc8cb3cb1866715c474e473694968d7e6b99ab"}, + {file = "numpy-2.5.2-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:cf7de32f486e4ac9e2d93b810f9e9ac72a728dd46a32a0bb403222f27f653514"}, + {file = "numpy-2.5.2-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:2ffa7bacab3e2ee1b19ed31766bb60bb380b68c23f051e199c5cc598afd68710"}, + {file = "numpy-2.5.2-cp315-cp315-win32.whl", hash = "sha256:6b588cc8f902d6bff201c19fd00c43ab8545671e3554d014e12e14139e5e8617"}, + {file = "numpy-2.5.2-cp315-cp315-win_amd64.whl", hash = "sha256:07d4e89f3a9ab0a9ba24264ccdb642b3dd951b2281e8883a5481a4aa79cc31a7"}, + {file = "numpy-2.5.2-cp315-cp315-win_arm64.whl", hash = "sha256:a610dc7e3c52edd39c2bc2375ff9c3fd59cb3ad00e4472d36f83bc1457145788"}, + {file = "numpy-2.5.2-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:40f4d451aed46a8046a1aae41c4e55fb3612273df9c502480135e1501576a34b"}, + {file = "numpy-2.5.2-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c081cbe16ba1ab53078e5ff29013621e33c509eedab055775d956427712c236e"}, + {file = "numpy-2.5.2-cp315-cp315t-macosx_14_0_arm64.whl", hash = "sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a"}, + {file = "numpy-2.5.2-cp315-cp315t-macosx_14_0_x86_64.whl", hash = "sha256:6a9bb119fb8dd21ba30b3f0e555b7e2b081bd9883af21ec9c1c633d161cda3a8"}, + {file = "numpy-2.5.2-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a839318485284a6fb31be4f8f2c91c8f2cb22f4543c4a8903f12b0671ffe07cc"}, + {file = "numpy-2.5.2-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba0a474801b8dc67b66bf465548abc90e82b44d2611b5770f33008dcabffe8ec"}, + {file = "numpy-2.5.2-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:0a4035ae1129ff8777f08bfbd44f1e5d8e9c049ce0c2dd78fc0d92c13e7251c0"}, + {file = "numpy-2.5.2-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:77843ca236b777e67f8d6b3660ea116e499612703a0ecd7093f316201eb9d8e2"}, + {file = "numpy-2.5.2-cp315-cp315t-win32.whl", hash = "sha256:7354826bc6f8f69402e9b7fe28d15fcd34feebd74f856f111585c5b0c9fb0251"}, + {file = "numpy-2.5.2-cp315-cp315t-win_amd64.whl", hash = "sha256:e5651f3f87add730ee6608d915009e19c911fba0cb000c7e3ea994b7d768eb12"}, + {file = "numpy-2.5.2-cp315-cp315t-win_arm64.whl", hash = "sha256:5f8e00be2ec6f45f4e8a41a527f68d44a7d96fee92a650e4d8b1326f77f61e6e"}, + {file = "numpy-2.5.2.tar.gz", hash = "sha256:d482d171c406ae88c5b19cad3b6a1c4c5209f886ab74bc44c2c865c23f52d860"}, ] [[package]] @@ -3171,7 +3238,7 @@ version = "5.0.0" description = "Readers and writers for OpenFAST files." optional = false python-versions = ">3.10" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "openfast_io-5.0.0-py3-none-any.whl", hash = "sha256:3558880af3af7d319e1644c3063eb44f067bd50db727b68dfc4578250deda093"}, {file = "openfast_io-5.0.0.tar.gz", hash = "sha256:5b683f2f381eee506d1a6ce90e3324273c027dea831b9dd969edc6254ce61241"}, @@ -3194,7 +3261,7 @@ version = "3.45.0" description = "OpenMDAO framework infrastructure" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "openmdao-3.45.0-py3-none-any.whl", hash = "sha256:ef01406fc29e763b69b979ffe7a3652351de5a68653da478cd4bbe02e2318f90"}, {file = "openmdao-3.45.0.tar.gz", hash = "sha256:2e342398386230706999433a0eafc3df566e71f89709479323c3f00ab1b69e54"}, @@ -3224,7 +3291,7 @@ version = "3.1.5" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, @@ -3239,7 +3306,7 @@ version = "1.3" description = "Offshore Renewables Balance of system and Installation Tool" optional = false python-versions = ">3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "orbit_nrel-1.3-py3-none-any.whl", hash = "sha256:011925d18deb982f8265f35c4af30047807f5a08dc0b0fcb5f594b4eab15c8a2"}, {file = "orbit_nrel-1.3.tar.gz", hash = "sha256:3cf16a4f4dec822c85b04743ca1ab6eebb830e47d2205b7cdcf95cb7ccc05537"}, @@ -3266,7 +3333,7 @@ version = "5.5.0" description = "Orderly set" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "orderly_set-5.5.0-py3-none-any.whl", hash = "sha256:46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7"}, {file = "orderly_set-5.5.0.tar.gz", hash = "sha256:e87185c8e4d8afa64e7f8160ee2c542a475b738bc891dc3f58102e654125e6ce"}, @@ -3294,14 +3361,14 @@ files = [ [[package]] name = "packaging" -version = "26.2" +version = "26.3" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.8" -groups = ["main", "dev", "examples"] +python-versions = ">=3.9" +groups = ["main", "dev", "examples", "floris"] files = [ - {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"}, - {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"}, + {file = "packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c"}, + {file = "packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79"}, ] [[package]] @@ -3310,7 +3377,7 @@ version = "2.3.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, @@ -3407,7 +3474,7 @@ version = "3.0.5" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "pandas-3.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2946e77e4a53cd248cbde631a12f0e51c8324ce354c3eba4d20147c1ad6f4282"}, @@ -3522,7 +3589,7 @@ version = "0.3.5" description = "parallel graph management and execution in heterogeneous computing" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "pathos-0.3.5-py3-none-any.whl", hash = "sha256:c95b04103c40a16c08db69cd4b5c52624d55208beadf1348681edece809ec4f8"}, {file = "pathos-0.3.5.tar.gz", hash = "sha256:8fe041b8545c5d3880a038f866022bdebf935e5cf68f56ed3407cb7e65193a61"}, @@ -3557,7 +3624,7 @@ version = "1.0.2" description = "A Python package for describing statistical models and for building design matrices." optional = false python-versions = ">=3.6" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a"}, {file = "patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0"}, @@ -3591,7 +3658,7 @@ version = "12.3.0" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] files = [ {file = "pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a"}, {file = "pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7"}, @@ -3692,14 +3759,14 @@ xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.11.0" +version = "4.11.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "platformdirs-4.11.0-py3-none-any.whl", hash = "sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74"}, - {file = "platformdirs-4.11.0.tar.gz", hash = "sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0"}, + {file = "platformdirs-4.11.2-py3-none-any.whl", hash = "sha256:7f89089b6ea71bda7962953edcf784b2e2d9d285b40ad88be2bb75c6e9d82ab4"}, + {file = "platformdirs-4.11.2.tar.gz", hash = "sha256:3a2ae5fca3520a01ab1be8b45613537f52ddf5b5f6f53d88233892dfbf0cd82d"}, ] [[package]] @@ -3761,7 +3828,7 @@ version = "0.3.7" description = "utilities for filesystem exploration and automated builds" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "pox-0.3.7-py3-none-any.whl", hash = "sha256:82a495249d13371314c1a5b5626a115e067ef5215d49530bf5efa37fbc25b56a"}, {file = "pox-0.3.7.tar.gz", hash = "sha256:0652f6f2103fe6d4ba638beb6fa8d3e8a68fd44bcb63315c614118515bcc3afb"}, @@ -3773,7 +3840,7 @@ version = "1.7.8" description = "distributed and parallel Python" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "ppft-1.7.8-py3-none-any.whl", hash = "sha256:d3e0e395215b14afc3dd5adfc032ccecfda2d4ed50dc7ded076cd1d215442843"}, {file = "ppft-1.7.8.tar.gz", hash = "sha256:5f696d4f397ae9b0af39b1faffb31957c51dfbc5a3815856472d4f4e872937ee"}, @@ -3883,12 +3950,12 @@ version = "3.0" description = "C parser in Python" optional = false python-versions = ">=3.10" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] -markers = {main = "implementation_name == \"pypy\"", dev = "implementation_name != \"PyPy\""} +markers = {main = "implementation_name == \"pypy\"", dev = "implementation_name != \"PyPy\"", floris = "implementation_name == \"pypy\""} [[package]] name = "pydoe3" @@ -3896,7 +3963,7 @@ version = "1.6.2" description = "Design of experiments for Python" optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "pydoe3-1.6.2-py2.py3-none-any.whl", hash = "sha256:21b5c3ef10a350bed01f59df54ae262fd1eda9983efac294b679988f311f3445"}, {file = "pydoe3-1.6.2.tar.gz", hash = "sha256:ff7377c30e0a2ea8af3f074723488779f557457c8b74029965896c30b8a1a541"}, @@ -3930,7 +3997,7 @@ version = "3.3.2" description = "pyparsing - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.9" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] files = [ {file = "pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"}, {file = "pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"}, @@ -3945,7 +4012,7 @@ version = "3.5.6" description = "A python implementation of GNU readline." optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "floris"] markers = "sys_platform == \"win32\"" files = [ {file = "pyreadline3-3.5.6-py3-none-any.whl", hash = "sha256:8449b734232e42a5dcd74048e39b60db2839a4c38cf3ae2bf7707d58b5389c0d"}, @@ -3984,7 +4051,7 @@ version = "0.38.0" description = "python-benedict is a dict subclass with keylist/keypath/keyattr support, normalized I/O operations (base64, csv, ini, json, pickle, plist, query-string, toml, xls, xml, yaml) and many utilities... for humans, obviously." optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "python_benedict-0.38.0-py3-none-any.whl", hash = "sha256:5f4cbdfdda245d3f2899a7fd9d59ee68e69e6d1e0d57693f8626f186a11fcc6b"}, {file = "python_benedict-0.38.0.tar.gz", hash = "sha256:71e066b73f15d2231927b3021469a1db57a3e96092a99917018b63f51329e49c"}, @@ -4012,7 +4079,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev", "examples"] +groups = ["main", "dev", "examples", "floris"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -4042,7 +4109,7 @@ version = "8.0.4" description = "A Python slugify application that also handles Unicode" optional = false python-versions = ">=3.7" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, @@ -4060,7 +4127,7 @@ version = "2026.3.post1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "pytz-2026.3.post1-py2.py3-none-any.whl", hash = "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815"}, @@ -4099,7 +4166,7 @@ version = "6.0.3" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, @@ -4182,7 +4249,7 @@ version = "27.1.0" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4"}, {file = "pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556"}, @@ -4287,7 +4354,7 @@ version = "0.37.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.10" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -4304,7 +4371,7 @@ version = "2.34.2" description = "Python HTTP for Humans." optional = false python-versions = ">=3.10" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, @@ -4371,7 +4438,7 @@ version = "2.10.4" description = "A reference open source controller toolset for wind turbine applications." optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "rosco-2.10.4-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:58b8744a6a8c66a16fb48c27b2846320cfc26b03bb5533581184543459ce804f"}, {file = "rosco-2.10.4-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:b6e932f0c6e2055950dfa81b1d5c10a5ce4278f5bd71f5cf52a3363c1938f574"}, @@ -4439,7 +4506,7 @@ version = "0.30.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, @@ -4565,7 +4632,7 @@ version = "2026.6.3" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.11" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7"}, @@ -4692,7 +4759,7 @@ version = "0.19.1" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93"}, {file = "ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993"}, @@ -4737,7 +4804,7 @@ version = "1.15.3" description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"}, @@ -4802,7 +4869,7 @@ version = "1.17.1" description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version == \"3.11\"" files = [ {file = "scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec"}, @@ -4882,7 +4949,7 @@ version = "1.18.0" description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.12" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version >= \"3.12\"" files = [ {file = "scipy-1.18.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:7bd21faaf5a1a3b2eff922d02db5f191b99a6518db9078a8fb23169f6d22259a"}, @@ -4936,28 +5003,6 @@ dev = ["click (<8.3.0)", "cython-lint (>=0.12.2)", "mypy (==1.19.1)", "pycodesty doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)", "tabulate"] test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "scipy-doctest (>=2.0.0)", "threadpoolctl"] -[[package]] -name = "seaborn" -version = "0.13.2" -description = "Statistical data visualization" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987"}, - {file = "seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7"}, -] - -[package.dependencies] -matplotlib = ">=3.4,<3.6.1 || >3.6.1" -numpy = ">=1.20,<1.24.0 || >1.24.0" -pandas = ">=1.2" - -[package.extras] -dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] -docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx (<6.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] -stats = ["scipy (>=1.7)", "statsmodels (>=0.12)"] - [[package]] name = "send2trash" version = "2.1.0" @@ -4980,7 +5025,7 @@ version = "2.1.2" description = "Manipulation and analysis of geometric objects" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "shapely-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7ae48c236c0324b4e139bea88a306a04ca630f49be66741b340729d380d8f52f"}, {file = "shapely-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eba6710407f1daa8e7602c347dfc94adc02205ec27ed956346190d66579eb9ea"}, @@ -5054,7 +5099,7 @@ version = "4.1.2" description = "Event discrete, process based simulation for Python." optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "simpy-4.1.2-py3-none-any.whl", hash = "sha256:43071f84b6512c9b4fcb33ef057f240ccb1d1f3b263f9b4f9229d072e310b372"}, {file = "simpy-4.1.2.tar.gz", hash = "sha256:76ef36b71e0436ba94e55febc001c78879e493a323f045bbcfbb0b216e9b1fbc"}, @@ -5066,7 +5111,7 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev", "examples"] +groups = ["main", "dev", "examples", "floris"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -5078,7 +5123,7 @@ version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, @@ -5086,14 +5131,14 @@ files = [ [[package]] name = "soupsieve" -version = "2.9.1" +version = "2.9.2" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "soupsieve-2.9.1-py3-none-any.whl", hash = "sha256:4f4477399246b7a0c720a88ca2454b11cd6bb9ae4c9d170140786e916776c14c"}, - {file = "soupsieve-2.9.1.tar.gz", hash = "sha256:c33e6605bbc71dd628b00c632d58ae607c22bade247e52553928f83bbb75b4ba"}, + {file = "soupsieve-2.9.2-py3-none-any.whl", hash = "sha256:8089a26fd974ca7a1f30276d3d8492ab266ab15af581642dfe8aa162e0c1c823"}, + {file = "soupsieve-2.9.2.tar.gz", hash = "sha256:4a55d8cf158a9c2e587fa4922f1bbb91d68ac829e2d6f25403a85747c71daf74"}, ] [[package]] @@ -5122,7 +5167,7 @@ version = "0.14.6" description = "Statistical computations and models for Python" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "statsmodels-0.14.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4ff0649a2df674c7ffb6fa1a06bffdb82a6adf09a48e90e000a15a6aaa734b0"}, {file = "statsmodels-0.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:109012088b3e370080846ab053c76d125268631410142daad2f8c10770e8e8d9"}, @@ -5202,7 +5247,7 @@ version = "1.3" description = "The most basic Text::Unidecode port" optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, @@ -5299,22 +5344,22 @@ files = [ [[package]] name = "tornado" -version = "6.5.7" +version = "6.5.8" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "tornado-6.5.7-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:148b2eb15c2c765a50796172c1e499649b35f30d2e3c3d3e15913cfa56bfb163"}, - {file = "tornado-6.5.7-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9da38de27f1da3b78a966f0dae12b5a1ea9afe72ca805d84ff06508272ddf100"}, - {file = "tornado-6.5.7-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8d759e71906ee783f8867b93bf26a265743da4c1e2f4a018464c1ba019862972"}, - {file = "tornado-6.5.7-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a46347a18f23fb92b396beebe0fb78f61dda0cc302445202c16203d8a18848b"}, - {file = "tornado-6.5.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7778b30bef919231265e91c69963ce0f49a1e9c07ac900bbe75b19ce2575ba92"}, - {file = "tornado-6.5.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e726f0c75da7726eec023aa62751ff8878bd2737e34fbdd33b1ae5897d2200f5"}, - {file = "tornado-6.5.7-cp39-abi3-win32.whl", hash = "sha256:f8de3bf12d3efdd0cbe7c8887868198f8a91415e3f29fcf258d9b8eb7b1d9ae4"}, - {file = "tornado-6.5.7-cp39-abi3-win_amd64.whl", hash = "sha256:de942f843533a039ef9fa3d9c88c7cd8a7c94553fb5ad0154270989b3d99a2c4"}, - {file = "tornado-6.5.7-cp39-abi3-win_arm64.whl", hash = "sha256:ff934fce95643af5f11efdae618eaa73d469dc588641e5c8d19295a0c65c4796"}, - {file = "tornado-6.5.7.tar.gz", hash = "sha256:66c513a76cda70d53907bc27cf1447557699c2e95aa48ba27a442ff61c3ddfc2"}, + {file = "tornado-6.5.8-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:cc6aa787d7cfab7c3d35189dc7a56fbd2399a569624c730c6b55b3d6531d0403"}, + {file = "tornado-6.5.8-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9715b5eb79735b2bcd454ce216a9275b7c0470e64ea1bf5742f78b2f72b26eeb"}, + {file = "tornado-6.5.8-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:547d63f450d570c14fe0e8db2cfb14c9bbd1c2503b4a6612586267955aa47b58"}, + {file = "tornado-6.5.8-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e2360a0ffbe145eca8af0b19cb7203d79b1a98dd4cccdd6b368f6f49c2e3808"}, + {file = "tornado-6.5.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5d242290bdf7ab3151bc1065fdd75c0dcc21cbc7b49f22a4c56329c2d6566d22"}, + {file = "tornado-6.5.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7b94ff0e128fe0542f3bd331fb44d06260fc4ac16881545159f34ef08aad4195"}, + {file = "tornado-6.5.8-cp39-abi3-win32.whl", hash = "sha256:67832909c4779c64942380cb5f044a5c6163d00831472d80e25e115de9917836"}, + {file = "tornado-6.5.8-cp39-abi3-win_amd64.whl", hash = "sha256:11881db6b7c168494be2c2d12e65931451bdf7ee718535418ae1d8855dd5a0ee"}, + {file = "tornado-6.5.8-cp39-abi3-win_arm64.whl", hash = "sha256:68a7468c7e289f8514d7d664101753903217eff1bb6822c6b5994a0b5f5bcb26"}, + {file = "tornado-6.5.8.tar.gz", hash = "sha256:9452e1b208a8bd771e2cb1f2ff564985b9b214bdebbe622793e1799e0a6bd23f"}, ] [[package]] @@ -5323,7 +5368,7 @@ version = "4.70.0" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.8" -groups = ["main", "examples"] +groups = ["main", "examples", "floris"] files = [ {file = "tqdm-4.70.0-py3-none-any.whl", hash = "sha256:7f585706bfddbdebf89daac705b2dfcc16890130727d3197ca62c732b4310953"}, {file = "tqdm-4.70.0.tar.gz", hash = "sha256:55b0b0dbd97462d06ebee91e4dac24ed4d4702be82b24f07e6c1d27e08cea220"}, @@ -5344,7 +5389,7 @@ version = "0.0.5" description = "Tracking progress of joblib.Parallel execution" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "tqdm_joblib-0.0.5-py3-none-any.whl", hash = "sha256:5948fccca627970cc8340dd56ac49d29222ed110b9ee39fd310b76a1483b471f"}, {file = "tqdm_joblib-0.0.5.tar.gz", hash = "sha256:34dd63c92e1b88b5118661a41eaf91001cac2687bfe217a4b6a9ab1bbf0f1c64"}, @@ -5355,19 +5400,19 @@ tqdm = "*" [[package]] name = "traitlets" -version = "5.15.1" +version = "5.16.1" description = "Traitlets Python configuration system" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "traitlets-5.15.1-py3-none-any.whl", hash = "sha256:770a53705f84b81ac107e83a1b3328ff2dae16094d8fc3cfc004e4b22dfd8e92"}, - {file = "traitlets-5.15.1.tar.gz", hash = "sha256:7b1c07854fe25acb39e009bae49f11b79ff6cbb2f27999104e9110e7a6b53722"}, + {file = "traitlets-5.16.1-py3-none-any.whl", hash = "sha256:f775618166caa0396c8e337099240f2bd3e5e917d203b2e6fbe21a58d3cb1f6b"}, + {file = "traitlets-5.16.1.tar.gz", hash = "sha256:ed900c2b631aa3a112811139fa97b8d2c3bad5e989656bba4b7e52c7852c18c1"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.17.0,<1.19)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] +test = ["argcomplete (>=3.0.3) ; python_version < \"3.12\"", "argcomplete (>=3.5.2) ; python_version >= \"3.12\"", "mypy (>=2.0) ; implementation_name != \"pypy\"", "pre-commit", "pytest (>=7.0,<10.0)", "pytest-mock", "pytest-mypy-testing ; implementation_name != \"pypy\""] [[package]] name = "typing-extensions" @@ -5375,7 +5420,7 @@ version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, @@ -5387,12 +5432,12 @@ version = "2026.3" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931"}, {file = "tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415"}, ] -markers = {main = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version < \"3.11\""} +markers = {main = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version < \"3.11\"", floris = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version < \"3.11\""} [[package]] name = "unified-momentum-model" @@ -5443,7 +5488,7 @@ version = "2.7.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.10" -groups = ["main", "dev"] +groups = ["main", "dev", "floris"] files = [ {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, @@ -5526,7 +5571,7 @@ version = "2.1.1" description = "Frameworks defining the inputs and outputs for systems engineering MDAO of wind turbine and plants." optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "windio-2.1.1-py3-none-any.whl", hash = "sha256:333820957a0b38651d1ea48df5a2544f17d4cf766cee7bb2b1caed5557e7d35b"}, {file = "windio-2.1.1.tar.gz", hash = "sha256:ca5581a8a54425695b7726713bbc878ad1f2073a767b568166fa1e8340ec7de9"}, @@ -5548,7 +5593,7 @@ version = "4.0.5" description = "Wind-Plant Integrated System Design & Engineering Model" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "floris"] files = [ {file = "wisdem-4.0.5-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5334e38e26efba43c9848de4a4a4fc681b438635f0b773aff01ba6ed29d61833"}, {file = "wisdem-4.0.5-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:8040476014ce81342a996dbb1b3355605a8fc0b824af7ea6d5b4a95735699895"}, @@ -5631,7 +5676,7 @@ version = "2025.6.1" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "xarray-2025.6.1-py3-none-any.whl", hash = "sha256:8b988b47f67a383bdc3b04c5db475cd165e580134c1f1943d52aee4a9c97651b"}, @@ -5658,7 +5703,7 @@ version = "2026.7.0" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.11" -groups = ["main"] +groups = ["main", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "xarray-2026.7.0-py3-none-any.whl", hash = "sha256:bf9dd130b93806dc78e90c1b7ac24851b31557b888674c53622235691cf21824"}, @@ -5682,4 +5727,4 @@ viz = ["cartopy (>=0.24)", "matplotlib (>=3.10)", "nc-time-axis", "seaborn"] [metadata] lock-version = "2.1" python-versions = ">3.10, <3.15" -content-hash = "917ef746b4a52e48fabccd07a22188031c78cfa94486416eb2af678990491c26" +content-hash = "4508ec537e13d01ad59e2bee93c66ec16f2707f259dde7b5b05f48b26f2cd972" diff --git a/pyproject.toml b/pyproject.toml index c270e91..99a7bae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "MITRotor" -version = "0.2.1" +version = "0.2.2" description = "" authors = ["Jaime Liew "] readme = "README.md" @@ -14,8 +14,15 @@ unified-momentum-model = {git = "https://github.com/Howland-Lab/Unified-Momentum pyyaml = "^6.0.1" floris = {git = "https://github.com/NatLabRockies/floris.git", branch = "dev/v5-beta"} rosco = "^2.10.4" -ruamel-yaml = "^0.19.1" -seaborn = "^0.13.2" +joblib = "^1.5.3" +tqdm-joblib = "^0.0.5" + +[tool.poetry.group.floris] +optional = true + +[tool.poetry.group.floris.dependencies] +floris = {git = "https://github.com/NatLabRockies/floris.git", branch = "dev/v5-beta"} +rosco = "^2.10.4" joblib = "^1.5.3" tqdm-joblib = "^0.0.5" diff --git a/tests/test_bem.py b/tests/test_bem.py index e58e7f4..2e4ddd8 100644 --- a/tests/test_bem.py +++ b/tests/test_bem.py @@ -170,3 +170,32 @@ def test_BEM_dimensionality(): for name in fields: val = np.asarray(getattr(sol, name)(grid=grid)) assert val.shape == expected_shape, f"{name}, {grid}" + # ========================= + # 3. Vectorized vs Loop + # ========================= + if Np > 0: # Only test vectorized case + # Solve in loop (scalar inputs) + sols_loop = [] + for i in range(Np): + sol_loop = bem(pitch[i], tsr[i], yaw=yaw[i], tilt=tilt[i]) + sols_loop.append(sol_loop) + + # Compare u4, w4 + u4_vec = np.asarray(sol.u4) + w4_vec = np.asarray(sol.w4) + + u4_loop = np.stack([np.asarray(s.u4) for s in sols_loop]) + w4_loop = np.stack([np.asarray(s.w4) for s in sols_loop]) + + np.testing.assert_allclose(u4_vec, u4_loop, atol=1e-5) + np.testing.assert_allclose(w4_vec, w4_loop, atol=1e-5) + + # Compare field outputs + for grid in ["rotor", "annulus", "sector"]: + for name in fields: + val_vec = np.asarray(getattr(sol, name)(grid=grid)) + val_loop = np.stack([ + np.asarray(getattr(s, name)(grid=grid)) + for s in sols_loop + ]) + np.testing.assert_allclose(val_vec, val_loop, atol=1e-5) From 4cc932e59c6b0c008ceaa511a7bea2d23f465faf Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Tue, 11 Aug 2026 17:40:33 -0400 Subject: [PATCH 49/50] Mention vectorization in quick start --- examples/MITRotor_quickstart.ipynb | 44 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/examples/MITRotor_quickstart.ipynb b/examples/MITRotor_quickstart.ipynb index f0be3db..b97cec5 100644 --- a/examples/MITRotor_quickstart.ipynb +++ b/examples/MITRotor_quickstart.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -63,7 +63,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -94,7 +94,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -119,7 +119,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -163,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -186,7 +186,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -211,7 +211,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -230,7 +230,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -260,7 +260,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -308,17 +308,17 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "SyntaxWarning: <>:7\n", - "invalid escape sequence '\\m'SyntaxWarning: <>:7\n", - "invalid escape sequence '\\m'SyntaxWarning: /var/folders/dt/wzb0_01j5yz8q2y9bz5sfjm00000gn/T/ipykernel_3191/2546713841.py:7\n", - "invalid escape sequence '\\m'" + "<>:7: SyntaxWarning: invalid escape sequence '\\m'\n", + "<>:7: SyntaxWarning: invalid escape sequence '\\m'\n", + "/var/folders/dt/wzb0_01j5yz8q2y9bz5sfjm00000gn/T/ipykernel_88069/2546713841.py:7: SyntaxWarning: invalid escape sequence '\\m'\n", + " axes[-1].set_xlabel(\"Radial position, $\\mu$ [-]\")\n" ] }, { @@ -327,7 +327,7 @@ "(0.0, 1.0)" ] }, - "execution_count": 24, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, @@ -357,7 +357,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If you're looking for a more exploratory script, see `example_03_pitch_tsr_contour.py`. If you're looking to run a simulation with multiple turbines in a wind farm configuration, see the quick start guide for `MITWindfarm`." + "If you're looking for a more exploratory script, see `example_03_pitch_tsr_contour.py`. If you're looking to run a simulation with multiple turbines in a wind farm configuration, see the quick start guide for `MITWindfarm`.\n", + "\n", + "Note that vectors of setpoints can also be passed in to solve multiple solutions, as long as the vectors are all the same length." ] }, { @@ -375,7 +377,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -451,16 +453,16 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 32, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, From fd9ee431fed0c39659c50d5f8082954f0e7bc49d Mon Sep 17 00:00:00 2001 From: Skylar Gering Date: Wed, 12 Aug 2026 06:39:23 -0400 Subject: [PATCH 50/50] Update dependencies and github tests to use poetry --- .github/workflows/pytest.yml | 12 +-- poetry.lock | 162 +++++++++++++++++------------------ pyproject.toml | 4 - 3 files changed, 87 insertions(+), 91 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 66aa75c..083bb1e 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -26,11 +26,11 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install . - pip install pytest + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Install dependencies with floris + run: poetry install --with floris - name: Run pytest - run: python -m pytest \ No newline at end of file + run: poetry run pytest \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 486c4ff..ca33940 100644 --- a/poetry.lock +++ b/poetry.lock @@ -147,7 +147,7 @@ version = "26.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.9" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, @@ -265,7 +265,7 @@ version = "5.2.3" description = "The fastest memoizing and caching Python library written in Rust" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "cachebox-5.2.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c2c89720547271d36e10cad2c7302bbe11f46eb39eead0a2c321c2d371b8f8b6"}, {file = "cachebox-5.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7f33d24e90dc8aa26762e25898c91a1223b66685420a28a3628fa2e006924f5"}, @@ -387,7 +387,7 @@ version = "2026.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775"}, {file = "certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55"}, @@ -399,7 +399,7 @@ version = "2.1.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.10" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "cffi-2.1.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be"}, {file = "cffi-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b"}, @@ -502,7 +502,7 @@ files = [ {file = "cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692"}, {file = "cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be"}, ] -markers = {main = "implementation_name == \"pypy\"", floris = "implementation_name == \"pypy\""} +markers = {floris = "implementation_name == \"pypy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -513,7 +513,7 @@ version = "1.6.5" description = "Time-handling functionality from netcdf4-python" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "cftime-1.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ad81e8cb0eb873b33c3d1e22c6168163fdc64daa8f7aeb4da8092f272575f4d"}, {file = "cftime-1.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12d95c6af852114a13301c5a61e41afdbd1542e72939c1083796f8418b9b8b0e"}, @@ -567,7 +567,7 @@ version = "3.4.9" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "charset_normalizer-3.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a"}, {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616"}, @@ -698,7 +698,7 @@ version = "15.0.1" description = "Colored terminal output for Python's logging module" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, @@ -731,7 +731,7 @@ version = "1.3.2" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.10" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934"}, @@ -809,7 +809,7 @@ version = "1.3.3" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.11" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, @@ -902,7 +902,7 @@ version = "0.10.2" description = "Python Control Systems Library" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "control-0.10.2-py3-none-any.whl", hash = "sha256:8f7b5c58f5ccd761a6c070e3dedceca4c53c7a9cf105fcc22caba7a67f99025a"}, {file = "control-0.10.2.tar.gz", hash = "sha256:d0cf63f6cfb68a4c8e827c26c3744d129e9777fedc9a5d86ca4740548f23a98b"}, @@ -924,7 +924,7 @@ version = "0.12.1" description = "Composable style cycles" optional = false python-versions = ">=3.8" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] files = [ {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, @@ -992,7 +992,7 @@ version = "9.1.0" description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "deepdiff-9.1.0-py3-none-any.whl", hash = "sha256:80c0460e1993b04f6f0ca79abf25548b129fd218478c4ebb08f80560f5d10610"}, {file = "deepdiff-9.1.0.tar.gz", hash = "sha256:07e9e366fab4297755153c4eab795ad4ef3cbd0d51660e847f5751c6bd727687"}, @@ -1029,7 +1029,7 @@ version = "0.4.1" description = "serialize all of Python" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d"}, {file = "dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa"}, @@ -1045,7 +1045,7 @@ version = "2.0.0" description = "An implementation of lxml.xmlfile for the standard library" optional = false python-versions = ">=3.8" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"}, {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"}, @@ -1106,7 +1106,7 @@ version = "4.6.6" description = "A controls-oriented engineering wake model." optional = false python-versions = ">=3.10, <3.15" -groups = ["main", "floris"] +groups = ["floris"] files = [] develop = false @@ -1138,7 +1138,7 @@ version = "4.63.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.10" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] files = [ {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b"}, {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94"}, @@ -1297,7 +1297,7 @@ version = "10.0" description = "Human friendly output for text interfaces using Python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, @@ -1312,7 +1312,7 @@ version = "3.18" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.9" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2"}, {file = "idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848"}, @@ -1486,7 +1486,7 @@ version = "1.5.3" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713"}, {file = "joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3"}, @@ -1510,7 +1510,7 @@ version = "1.9.2" description = "Merge a series of JSON documents." optional = false python-versions = "*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "jsonmerge-1.9.2-py3-none-any.whl", hash = "sha256:cab93ee7763fb51a4a09bbdab2eacf499ffb208ab94247ae86acea3e0e823b05"}, {file = "jsonmerge-1.9.2.tar.gz", hash = "sha256:c43757e0180b0e19b7ae4c130ad42a07cc580c31912f61f4823e8eaf2fa394a3"}, @@ -1537,7 +1537,7 @@ version = "4.26.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.10" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, @@ -1568,7 +1568,7 @@ version = "2025.9.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, @@ -1878,7 +1878,7 @@ version = "1.5.0" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.10" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] files = [ {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374"}, {file = "kiwisolver-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd"}, @@ -2270,7 +2270,7 @@ version = "0.2.5" description = "Agent based processs modeling." optional = false python-versions = "*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "marmot-agents-0.2.5.tar.gz", hash = "sha256:d0038c28928681b74352397a357f290da00c86a10c9626219b3ae36899faa915"}, {file = "marmot_agents-0.2.5-py3-none-any.whl", hash = "sha256:f7678a830593222436396163fb0788d9d113bf84afb956b8854aad465830c2a6"}, @@ -2285,7 +2285,7 @@ version = "3.10.9" description = "Python plotting package" optional = false python-versions = ">=3.10" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "matplotlib-3.10.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77210dce9cb8153dffc967efaae990543392563d5a376d4dd8539bebcb0ed217"}, @@ -2365,7 +2365,7 @@ version = "3.11.1" description = "Python plotting package" optional = false python-versions = ">=3.11" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "matplotlib-3.11.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b7cf158e7add54a8d51ac9b5a84abd6d4e13ed4951b4f25f1c5139f41c2addb2"}, @@ -2466,7 +2466,7 @@ version = "1.3.0" description = "A design-oriented mooring system library for Python" optional = false python-versions = ">=3.8" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "moorpy-1.3.0-py3-none-any.whl", hash = "sha256:2a6bf0f9db32fd49624471aeb152925ede383c0414db853c47069d5b3cd55b12"}, {file = "moorpy-1.3.0.tar.gz", hash = "sha256:ccef5e65a8a0f65be48e0fc39275918c318390937bf426c26a96d5fda0692256"}, @@ -2489,7 +2489,7 @@ version = "0.70.19" description = "better multiprocessing and multithreading in Python" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "multiprocess-0.70.19-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:02e5c35d7d6cd2bdc89c1858867f7bde4012837411023a4696c148c1bdd7c80e"}, {file = "multiprocess-0.70.19-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:79576c02d1207ec405b00cabf2c643c36070800cca433860e14539df7818b2aa"}, @@ -2693,7 +2693,7 @@ version = "1.7.3" description = "Provides an object-oriented python interface to the netCDF version 4 library" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version < \"3.11\" and platform_system == \"Windows\" and platform_machine == \"ARM64\"" files = [ {file = "netcdf4-1.7.3-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:db761afd3a6b9482df018c4783e0bdf99141a41db1f14c68c89986effb182d57"}, @@ -2724,7 +2724,7 @@ version = "1.7.4" description = "Provides an object-oriented python interface to the netCDF version 4 library" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] markers = "platform_system != \"Windows\" or platform_machine != \"ARM64\" or python_version >= \"3.11\"" files = [ {file = "netcdf4-1.7.4-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:b1c1a7ea3678db76bf33d14f7e202385d634db38c5e70d8cf4895971023eebb9"}, @@ -2769,7 +2769,7 @@ version = "3.4.2" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version < \"3.11\"" files = [ {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, @@ -2790,7 +2790,7 @@ version = "3.6" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = ">=3.11" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version == \"3.14\"" files = [ {file = "networkx-3.6-py3-none-any.whl", hash = "sha256:cdb395b105806062473d3be36458d8f1459a4e4b98e236a66c3a48996e07684f"}, @@ -2814,7 +2814,7 @@ version = "3.6.1" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = "!=3.14.1,>=3.11" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version < \"3.14\" and python_version >= \"3.11\"" files = [ {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, @@ -2881,7 +2881,7 @@ version = "2.14.1" description = "Fast numerical expression evaluator for NumPy" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version < \"3.11\"" files = [ {file = "numexpr-2.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0fab3fd06a04f6b86102552b26aa5d85e20ac7d8296c15764c726eeabae6cc8"}, @@ -2952,7 +2952,7 @@ version = "2.14.2" description = "Fast numerical expression evaluator for NumPy" optional = false python-versions = ">=3.11" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version >= \"3.11\"" files = [ {file = "numexpr-2.14.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2aa65ddc2243f19c6915f34ee0978b4a2df20f297230a793c4ee6d55f3472599"}, @@ -3238,7 +3238,7 @@ version = "5.0.0" description = "Readers and writers for OpenFAST files." optional = false python-versions = ">3.10" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "openfast_io-5.0.0-py3-none-any.whl", hash = "sha256:3558880af3af7d319e1644c3063eb44f067bd50db727b68dfc4578250deda093"}, {file = "openfast_io-5.0.0.tar.gz", hash = "sha256:5b683f2f381eee506d1a6ce90e3324273c027dea831b9dd969edc6254ce61241"}, @@ -3261,7 +3261,7 @@ version = "3.45.0" description = "OpenMDAO framework infrastructure" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "openmdao-3.45.0-py3-none-any.whl", hash = "sha256:ef01406fc29e763b69b979ffe7a3652351de5a68653da478cd4bbe02e2318f90"}, {file = "openmdao-3.45.0.tar.gz", hash = "sha256:2e342398386230706999433a0eafc3df566e71f89709479323c3f00ab1b69e54"}, @@ -3291,7 +3291,7 @@ version = "3.1.5" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" optional = false python-versions = ">=3.8" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, @@ -3306,7 +3306,7 @@ version = "1.3" description = "Offshore Renewables Balance of system and Installation Tool" optional = false python-versions = ">3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "orbit_nrel-1.3-py3-none-any.whl", hash = "sha256:011925d18deb982f8265f35c4af30047807f5a08dc0b0fcb5f594b4eab15c8a2"}, {file = "orbit_nrel-1.3.tar.gz", hash = "sha256:3cf16a4f4dec822c85b04743ca1ab6eebb830e47d2205b7cdcf95cb7ccc05537"}, @@ -3333,7 +3333,7 @@ version = "5.5.0" description = "Orderly set" optional = false python-versions = ">=3.8" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "orderly_set-5.5.0-py3-none-any.whl", hash = "sha256:46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7"}, {file = "orderly_set-5.5.0.tar.gz", hash = "sha256:e87185c8e4d8afa64e7f8160ee2c542a475b738bc891dc3f58102e654125e6ce"}, @@ -3365,7 +3365,7 @@ version = "26.3" description = "Core utilities for Python packages" optional = false python-versions = ">=3.9" -groups = ["main", "dev", "examples", "floris"] +groups = ["dev", "examples", "floris"] files = [ {file = "packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c"}, {file = "packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79"}, @@ -3377,7 +3377,7 @@ version = "2.3.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version < \"3.11\"" files = [ {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, @@ -3474,7 +3474,7 @@ version = "3.0.5" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.11" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version >= \"3.11\"" files = [ {file = "pandas-3.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2946e77e4a53cd248cbde631a12f0e51c8324ce354c3eba4d20147c1ad6f4282"}, @@ -3589,7 +3589,7 @@ version = "0.3.5" description = "parallel graph management and execution in heterogeneous computing" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "pathos-0.3.5-py3-none-any.whl", hash = "sha256:c95b04103c40a16c08db69cd4b5c52624d55208beadf1348681edece809ec4f8"}, {file = "pathos-0.3.5.tar.gz", hash = "sha256:8fe041b8545c5d3880a038f866022bdebf935e5cf68f56ed3407cb7e65193a61"}, @@ -3624,7 +3624,7 @@ version = "1.0.2" description = "A Python package for describing statistical models and for building design matrices." optional = false python-versions = ">=3.6" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a"}, {file = "patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0"}, @@ -3658,7 +3658,7 @@ version = "12.3.0" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] files = [ {file = "pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a"}, {file = "pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7"}, @@ -3828,7 +3828,7 @@ version = "0.3.7" description = "utilities for filesystem exploration and automated builds" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "pox-0.3.7-py3-none-any.whl", hash = "sha256:82a495249d13371314c1a5b5626a115e067ef5215d49530bf5efa37fbc25b56a"}, {file = "pox-0.3.7.tar.gz", hash = "sha256:0652f6f2103fe6d4ba638beb6fa8d3e8a68fd44bcb63315c614118515bcc3afb"}, @@ -3840,7 +3840,7 @@ version = "1.7.8" description = "distributed and parallel Python" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "ppft-1.7.8-py3-none-any.whl", hash = "sha256:d3e0e395215b14afc3dd5adfc032ccecfda2d4ed50dc7ded076cd1d215442843"}, {file = "ppft-1.7.8.tar.gz", hash = "sha256:5f696d4f397ae9b0af39b1faffb31957c51dfbc5a3815856472d4f4e872937ee"}, @@ -3950,12 +3950,12 @@ version = "3.0" description = "C parser in Python" optional = false python-versions = ">=3.10" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] -markers = {main = "implementation_name == \"pypy\"", dev = "implementation_name != \"PyPy\"", floris = "implementation_name == \"pypy\""} +markers = {dev = "implementation_name != \"PyPy\"", floris = "implementation_name == \"pypy\""} [[package]] name = "pydoe3" @@ -3963,7 +3963,7 @@ version = "1.6.2" description = "Design of experiments for Python" optional = false python-versions = "*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "pydoe3-1.6.2-py2.py3-none-any.whl", hash = "sha256:21b5c3ef10a350bed01f59df54ae262fd1eda9983efac294b679988f311f3445"}, {file = "pydoe3-1.6.2.tar.gz", hash = "sha256:ff7377c30e0a2ea8af3f074723488779f557457c8b74029965896c30b8a1a541"}, @@ -3997,7 +3997,7 @@ version = "3.3.2" description = "pyparsing - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.9" -groups = ["main", "examples", "floris"] +groups = ["examples", "floris"] files = [ {file = "pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"}, {file = "pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"}, @@ -4012,7 +4012,7 @@ version = "3.5.6" description = "A python implementation of GNU readline." optional = false python-versions = ">=3.8" -groups = ["main", "floris"] +groups = ["floris"] markers = "sys_platform == \"win32\"" files = [ {file = "pyreadline3-3.5.6-py3-none-any.whl", hash = "sha256:8449b734232e42a5dcd74048e39b60db2839a4c38cf3ae2bf7707d58b5389c0d"}, @@ -4051,7 +4051,7 @@ version = "0.38.0" description = "python-benedict is a dict subclass with keylist/keypath/keyattr support, normalized I/O operations (base64, csv, ini, json, pickle, plist, query-string, toml, xls, xml, yaml) and many utilities... for humans, obviously." optional = false python-versions = "*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "python_benedict-0.38.0-py3-none-any.whl", hash = "sha256:5f4cbdfdda245d3f2899a7fd9d59ee68e69e6d1e0d57693f8626f186a11fcc6b"}, {file = "python_benedict-0.38.0.tar.gz", hash = "sha256:71e066b73f15d2231927b3021469a1db57a3e96092a99917018b63f51329e49c"}, @@ -4079,7 +4079,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev", "examples", "floris"] +groups = ["dev", "examples", "floris"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -4109,7 +4109,7 @@ version = "8.0.4" description = "A Python slugify application that also handles Unicode" optional = false python-versions = ">=3.7" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, @@ -4127,7 +4127,7 @@ version = "2026.3.post1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version < \"3.11\"" files = [ {file = "pytz-2026.3.post1-py2.py3-none-any.whl", hash = "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815"}, @@ -4249,7 +4249,7 @@ version = "27.1.0" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.8" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4"}, {file = "pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556"}, @@ -4354,7 +4354,7 @@ version = "0.37.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.10" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -4371,7 +4371,7 @@ version = "2.34.2" description = "Python HTTP for Humans." optional = false python-versions = ">=3.10" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, @@ -4438,7 +4438,7 @@ version = "2.10.4" description = "A reference open source controller toolset for wind turbine applications." optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "rosco-2.10.4-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:58b8744a6a8c66a16fb48c27b2846320cfc26b03bb5533581184543459ce804f"}, {file = "rosco-2.10.4-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:b6e932f0c6e2055950dfa81b1d5c10a5ce4278f5bd71f5cf52a3363c1938f574"}, @@ -4506,7 +4506,7 @@ version = "0.30.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] markers = "python_version < \"3.11\"" files = [ {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, @@ -4632,7 +4632,7 @@ version = "2026.6.3" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.11" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] markers = "python_version >= \"3.11\"" files = [ {file = "rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7"}, @@ -4759,7 +4759,7 @@ version = "0.19.1" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93"}, {file = "ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993"}, @@ -5025,7 +5025,7 @@ version = "2.1.2" description = "Manipulation and analysis of geometric objects" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "shapely-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7ae48c236c0324b4e139bea88a306a04ca630f49be66741b340729d380d8f52f"}, {file = "shapely-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eba6710407f1daa8e7602c347dfc94adc02205ec27ed956346190d66579eb9ea"}, @@ -5099,7 +5099,7 @@ version = "4.1.2" description = "Event discrete, process based simulation for Python." optional = false python-versions = ">=3.8" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "simpy-4.1.2-py3-none-any.whl", hash = "sha256:43071f84b6512c9b4fcb33ef057f240ccb1d1f3b263f9b4f9229d072e310b372"}, {file = "simpy-4.1.2.tar.gz", hash = "sha256:76ef36b71e0436ba94e55febc001c78879e493a323f045bbcfbb0b216e9b1fbc"}, @@ -5111,7 +5111,7 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev", "examples", "floris"] +groups = ["dev", "examples", "floris"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -5123,7 +5123,7 @@ version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" optional = false python-versions = "*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, @@ -5167,7 +5167,7 @@ version = "0.14.6" description = "Statistical computations and models for Python" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "statsmodels-0.14.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4ff0649a2df674c7ffb6fa1a06bffdb82a6adf09a48e90e000a15a6aaa734b0"}, {file = "statsmodels-0.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:109012088b3e370080846ab053c76d125268631410142daad2f8c10770e8e8d9"}, @@ -5247,7 +5247,7 @@ version = "1.3" description = "The most basic Text::Unidecode port" optional = false python-versions = "*" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, @@ -5389,7 +5389,7 @@ version = "0.0.5" description = "Tracking progress of joblib.Parallel execution" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "tqdm_joblib-0.0.5-py3-none-any.whl", hash = "sha256:5948fccca627970cc8340dd56ac49d29222ed110b9ee39fd310b76a1483b471f"}, {file = "tqdm_joblib-0.0.5.tar.gz", hash = "sha256:34dd63c92e1b88b5118661a41eaf91001cac2687bfe217a4b6a9ab1bbf0f1c64"}, @@ -5420,7 +5420,7 @@ version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, @@ -5432,12 +5432,12 @@ version = "2026.3" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931"}, {file = "tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415"}, ] -markers = {main = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version < \"3.11\"", floris = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version < \"3.11\""} +markers = {floris = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version < \"3.11\""} [[package]] name = "unified-momentum-model" @@ -5488,7 +5488,7 @@ version = "2.7.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.10" -groups = ["main", "dev", "floris"] +groups = ["dev", "floris"] files = [ {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, @@ -5571,7 +5571,7 @@ version = "2.1.1" description = "Frameworks defining the inputs and outputs for systems engineering MDAO of wind turbine and plants." optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "windio-2.1.1-py3-none-any.whl", hash = "sha256:333820957a0b38651d1ea48df5a2544f17d4cf766cee7bb2b1caed5557e7d35b"}, {file = "windio-2.1.1.tar.gz", hash = "sha256:ca5581a8a54425695b7726713bbc878ad1f2073a767b568166fa1e8340ec7de9"}, @@ -5593,7 +5593,7 @@ version = "4.0.5" description = "Wind-Plant Integrated System Design & Engineering Model" optional = false python-versions = ">=3.9" -groups = ["main", "floris"] +groups = ["floris"] files = [ {file = "wisdem-4.0.5-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5334e38e26efba43c9848de4a4a4fc681b438635f0b773aff01ba6ed29d61833"}, {file = "wisdem-4.0.5-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:8040476014ce81342a996dbb1b3355605a8fc0b824af7ea6d5b4a95735699895"}, @@ -5676,7 +5676,7 @@ version = "2025.6.1" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.10" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version < \"3.11\"" files = [ {file = "xarray-2025.6.1-py3-none-any.whl", hash = "sha256:8b988b47f67a383bdc3b04c5db475cd165e580134c1f1943d52aee4a9c97651b"}, @@ -5703,7 +5703,7 @@ version = "2026.7.0" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.11" -groups = ["main", "floris"] +groups = ["floris"] markers = "python_version >= \"3.11\"" files = [ {file = "xarray-2026.7.0-py3-none-any.whl", hash = "sha256:bf9dd130b93806dc78e90c1b7ac24851b31557b888674c53622235691cf21824"}, @@ -5727,4 +5727,4 @@ viz = ["cartopy (>=0.24)", "matplotlib (>=3.10)", "nc-time-axis", "seaborn"] [metadata] lock-version = "2.1" python-versions = ">3.10, <3.15" -content-hash = "4508ec537e13d01ad59e2bee93c66ec16f2707f259dde7b5b05f48b26f2cd972" +content-hash = "5115538db144c529f7a4929f110cf1cfb41be0ee4dbe4cd13e5b9c874d6194ec" diff --git a/pyproject.toml b/pyproject.toml index 99a7bae..7642016 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,10 +12,6 @@ numpy = "^2.2.1" scipy = ">=1.6" unified-momentum-model = {git = "https://github.com/Howland-Lab/Unified-Momentum-Model.git"} pyyaml = "^6.0.1" -floris = {git = "https://github.com/NatLabRockies/floris.git", branch = "dev/v5-beta"} -rosco = "^2.10.4" -joblib = "^1.5.3" -tqdm-joblib = "^0.0.5" [tool.poetry.group.floris] optional = true